<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<!--[if IE]><meta http-equiv="X-UA-Compatible" content="IE=edge"><![endif]-->
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="generator" content="Asciidoctor 1.5.8">
<title>ElasticSearch Java API v6.8.0 (初稿)</title>
<style>
/* normalize.css */

button, hr, input {
    overflow: visible
}

audio, canvas, progress, video {
    display: inline-block
}

progress, sub, sup {
    vertical-align: baseline
}

html {
    font-family: sans-serif;
    line-height: 1.15;
    -ms-text-size-adjust: 100%;
    -webkit-text-size-adjust: 100%
}

body {
    margin: 0
}

menu, article, aside, details, footer, header, nav, section {
    display: block
}

h1 {
    font-size: 2em;
    margin: .67em 0
}

figcaption, figure, main {
    display: block
}

figure {
    margin: 1em 40px
}

hr {
    box-sizing: content-box;
    height: 0
}

code, kbd, pre, samp {
    font-family: monospace, monospace;
    font-size: 1em
}

a {
    background-color: transparent;
    -webkit-text-decoration-skip: objects
}

a:active, a:hover {
    outline-width: 0
}

abbr[title] {
    border-bottom: none;
    text-decoration: underline;
    text-decoration: underline dotted
}

b, strong {
    font-weight: bolder
}

dfn {
    font-style: italic
}

mark {
    background-color: #ff0;
    color: #000
}

small {
    font-size: 80%
}

sub, sup {
    font-size: 75%;
    line-height: 0;
    position: relative
}

sub {
    bottom: -.25em
}

sup {
    top: -.5em
}

audio:not([controls]) {
    display: none;
    height: 0
}

img {
    border-style: none
}

svg:not(:root) {
    overflow: hidden
}

button, input, optgroup, select, textarea {
    font-family: sans-serif;
    font-size: 100%;
    line-height: 1.15;
    margin: 0
}

button, input {
}

button, select {
    text-transform: none
}

[type=submit], [type=reset], button, html [type=button] {
    -webkit-appearance: button
}

[type=button]::-moz-focus-inner, [type=reset]::-moz-focus-inner, [type=submit]::-moz-focus-inner, button::-moz-focus-inner {
    border-style: none;
    padding: 0
}

[type=button]:-moz-focusring, [type=reset]:-moz-focusring, [type=submit]:-moz-focusring, button:-moz-focusring {
    outline: ButtonText dotted 1px
}

fieldset {
    border: 1px solid silver;
    margin: 0 2px;
    padding: .35em .625em .75em
}

legend {
    box-sizing: border-box;
    color: inherit;
    display: table;
    max-width: 100%;
    padding: 0;
    white-space: normal
}

progress {
}

textarea {
    overflow: auto
}

[type=checkbox], [type=radio] {
    box-sizing: border-box;
    padding: 0
}

[type=number]::-webkit-inner-spin-button, [type=number]::-webkit-outer-spin-button {
    height: auto
}

[type=search] {
    -webkit-appearance: textfield;
    outline-offset: -2px
}

[type=search]::-webkit-search-cancel-button, [type=search]::-webkit-search-decoration {
    -webkit-appearance: none
}

::-webkit-file-upload-button {
    -webkit-appearance: button;
    font: inherit
}

summary {
    display: list-item
}

[hidden], template {
    display: none
}

/*# sourceMappingURL=normalize.min.css.map */

/* tocbot 2.1.4 */

.toc {
    overflow-y: auto
}

.toc > ul {
    overflow: hidden;
    position: relative
}

.toc-list {
    margin: 0;
    padding-left: 10px
}

a.toc-link {
    color: currentColor;
    height: 100%
}

.is-collapsible {
    max-height: 1000px;
    overflow: hidden;
    transition: all 300ms ease-in-out
}

.is-collapsed {
    max-height: 0
}

.is-position-fixed {
    position: fixed !important;
    top: 0
}

.is-active-link {
    font-weight: 700
}

.toc-link::before {
    background-color: #f9f9fb;
    content: ' ';
    display: inline-block;
    height: inherit;
    left: 8px;
    margin-top: -1px;
    position: absolute;
    width: 2px
}

.is-active-link::before {
    background-color: #54BC4B
}


/* Activiti Specific */

body {
    color: #494d55;
    font-size: 16px;
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
}

html, body {
    height: 100%;
    width: 100%;
    background: #f9f9f9;
    font-family: "Helvetica Neue", Helvetica, Roboto, Arial, sans-serif;
    color: #484848
}

.page-wrapper {
    min-height: 100%;
    /* equal to footer height */
    margin-bottom: -50px;
}

.page-wrapper:after {
    content: "";
    display: block;
    height: 50px;
}

#header {
    position: fixed;
    top: 0px;
    z-index: 100000;
    width: 100%;
}

#header > h1 {
    background-image: radial-gradient(circle, #1280e1 0%, #002069 100%);
    color: #f9f9f9;
    padding: 20px 0 20px 20px;
    font-size: 3em;
    font-weight: 800;
    line-height: 1.1;
    margin: 0;
}

#header > h1:before {
    background-size: 180px 54px;
    background-repeat: no-repeat;
    width: 337px;
    height: 54px;
    display: inline-block;
    content: '';
    margin-right: 30px;
}

#author {
    margin-left: 25%;
    font-size: 40px;
}

#content {
    margin: 129px 0 0 27%;
    padding: 10px 40px 0 20px;
    padding-right: 40px;
    line-height: 1.7;
    width: 67%;
    overflow-x: auto;
}

h2, h3, h4, h5, h6 {
    color: #00345a;
}

h2 {
    font-size: 26px;
    margin-top: 0;
    margin-bottom: 20px;
    font-weight: bold;
    padding-bottom: 10px;
    border-bottom: 1px solid #d7d7d7;
}

h3 {
    font-size: 18px;
    margin-top: 0;
    margin-bottom: 0;
    font-weight: bold;
    padding-bottom: 10px;
    /*border-bottom: 1px solid #d7d7d7;*/
}

h4 {
    font-size: 16px;
    font-weight: bold;
}

h5 {
    font-size: 14px;
    font-weight: bold;
}

h6, h7 {
    font-size: 14px;
    font-weight: bold;
    margin-top: 0;
    margin-bottom: 0;
}

.sect1, .sect2 {
    margin-bottom: 20px;
}

.clear {
    clear: both;
}

.note, .listingblock, .literalblock {
    overflow-x: auto;
    position: relative;
    width: 100%;
    margin: 0 0 15px 0;
    background-color: #F0F0F0;
    border-left: 3px solid #00a9e5;
    display: inline-flex;
    padding-left: 10px;
}

table.tableblock {
    width: 100%;
    max-width: 100%;
    margin-bottom: 20px;
    background-color: transparent;
    border-spacing: 0;
    border-collapse: collapse;
    border: 1px solid #ddd;
    table-layout: fixed;
}

table.tableblock > caption + thead > tr:first-child > td, table.tableblock > caption + thead > tr:first-child > th, table.tableblock > colgroup + thead > tr:first-child > td, table.tableblock > colgroup + thead > tr:first-child > th, table.tableblock > thead:first-child > tr:first-child > td, table.tableblock > thead:first-child > tr:first-child > th {
    border-top: 0;
}

table.tableblock > thead > tr > th {
    border-bottom-color: #8bd6d8;
}

table.tableblock > thead > tr > th {
    vertical-align: bottom;
    border-bottom: 1px solid #ddd;
}

table.tableblock > tbody > tr > td, table.tableblock > tbody > tr > th, table.tableblock > tfoot > tr > td, table.tableblock > tfoot > tr > th, table.tableblock > thead > tr > td, table.tableblock > thead > tr > th {
    padding: 8px;
    line-height: 1.42857143;
    vertical-align: top;
    border-top: 1px solid #ddd;
}

th {
    text-align: left;
}

table.tableblock > tbody > tr:nth-of-type(odd) {
    background-color: #f5f5f5;
}

table.tableblock > tbody > tr:nth-of-type(odd) {
    background-color: #f9f9f9;
}

td > p {
    margin: 0;
}

td.content {
    white-space: normal;
}

pre, td, th {
    white-space: pre-wrap;
    white-space: -moz-pre-wrap;
    white-space: -pre-wrap;
    white-space: -o-pre-wrap;
    word-wrap: break-word;
}

img {
    max-width: 100%;
}

a {
    color: #007387;
}

a:hover {
    color: #004c59;
}

#toc-parent {
    width: 23%;
    float: left;
    height: 100%;
    overflow-y: auto;
    position: fixed;
    padding: 10px;
    border-right: 1px solid #ccc;
}

#generated-toc {
    width: 100%;
    height: 100%;
    font-size: 16px;
}

.toc-link {
    text-decoration: none;
}

.toc-list {
    margin: 0 20px 0 10px;
}

.toc-list-item {
    padding: 4px 0 4px 0;
}


div.sect5 p {
    margin-top: 0;
    margin-bottom: 0;
}

div.sect5 code {
    font-family: "Helvetica Neue", Helvetica, Roboto, Arial, sans-serif;
}

.warning td.icon {
    background: url('../images/warning.png') no-repeat 0 45%;
    width: 70px;
}

.warning td.icon .title {
    visibility: hidden;
}

.important td.icon {
    background: url('../images/important.png') no-repeat 0 45%;
    width: 70px;
}

.important td.icon .title {
    visibility: hidden;
}

.note td.icon {
    background: url('../images/note.png') no-repeat 0 45%;
    width: 60px;
}

.note td.icon .title {
    visibility: hidden;
}

.conum[data-value] {
    display: inline-block;
    color: #fff !important;
    background-color: rgba(0, 0, 0, 0.8);
    -webkit-border-radius: 100px;
    border-radius: 100px;
    text-align: center;
    width: 1.67em;
    height: 1.67em;
    font-size: 0.75em;
    line-height: 1.67em;
    font-family: "Open Sans", "Sans", sans-serif;
    font-style: normal;
    font-weight: bold;
}

.conum[data-value] + b {
    display: none;
}

.conum[data-value]:after {
    content: attr(data-value);
}

*:not(pre) > code {
    font-size: .9375em;
    font-weight: normal;
    color: rgba(0, 0, 0, 0.9);
    background-color: #eaeaef;
    -webkit-border-radius: 4px;
    border-radius: 4px;
    line-height: 1.45;
    padding: 0.1em 0.5ex;
    word-spacing: -.15em;
}

.admonitionblock {
    background: #f2f2f3;
    padding: 10px;
    min-height: 80px;
    margin: 15px 0;
    border-radius: 5px;
    position: relative;
}

h1 {
    filter: alpha(Opacity=93);
    -moz-opacity: 0.93;
    opacity: 0.93;
}

.choose-version {
    position: fixed;
    right: 5px;
    z-index: 9999;
}
</style>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css">
<script type="text/javascript">

    /*
     * Tocbot.min.js version 2.1.4
     */

    !function (e) {
        function t(o) {
            if (n[o]) return n[o].exports;
            var i = n[o] = {exports: {}, id: o, loaded: !1};
            return e[o].call(i.exports, i, i.exports, t), i.loaded = !0, i.exports
        }

        var n = {};
        return t.m = e, t.c = n, t.p = "", t(0)
    }([/*!*************************!*\
   !*** ./src/js/index.js ***!
   \*************************/
        function (e, t, n) {
            var o, i, r;
            (function (l) {
                !function (n, l) {
                    i = [], o = l(n), r = "function" == typeof o ? o.apply(t, i) : o, !(void 0 !== r && (e.exports = r))
                }("undefined" != typeof l ? l : this.window || this.global, function (e) {
                    "use strict";

                    function t() {
                        for (var e = {}, t = 0; t < arguments.length; t++) {
                            var n = arguments[t];
                            for (var o in n) h.call(n, o) && (e[o] = n[o])
                        }
                        return e
                    }

                    function o(e, t, n) {
                        t || (t = 250);
                        var o, i;
                        return function () {
                            var r = n || this, l = +new Date, s = arguments;
                            o && l < o + t ? (clearTimeout(i), i = setTimeout(function () {
                                o = l, e.apply(r, s)
                            }, t)) : (o = l, e.apply(r, s))
                        }
                    }

                    var i, r, l, s = n(/*! smooth-scroll */1), c = n(/*! ./default-options.js */2), a = {}, u = {},
                        d = n(/*! ./build-html.js */3), f = n(/*! ./parse-content.js */4),
                        m = (e.document, document.body, !!e.document.querySelector && !!e.addEventListener),
                        h = Object.prototype.hasOwnProperty;
                    return u.destroy = function () {
                        try {
                            document.querySelector(a.tocSelector).innerHTML = ""
                        } catch (e) {
                            console.warn("Element not found: " + a.tocSelector)
                        }
                        document.removeEventListener("scroll", this._scrollListener, !1), document.removeEventListener("resize", this._scrollListener, !1), i && document.removeEventListener("click", this._clickListener, !1), s && s.destroy()
                    }, u.init = function (e) {
                        if (m && (a = t(c, e || {}), this.options = a, this.state = {}, i = d(a), r = f(a), this._buildHtml = i, this._parseContent = r, u.destroy(), l = r.selectHeadings(a.contentSelector, a.headingSelector), null !== l)) {
                            var n = r.nestHeadingsArray(l), h = n.nest;
                            return i.render(a.tocSelector, h), this._scrollListener = o(function () {
                                i.updateToc(l)
                            }, a.throttleTimeout), this._scrollListener(), document.addEventListener("scroll", this._scrollListener, !1), document.addEventListener("resize", this._scrollListener, !1), this._clickListener = o(function (e) {
                                i.disableTocAnimation(e), i.updateToc(l)
                            }, a.throttleTimeout), document.addEventListener("click", this._clickListener, !1), s && (this.smoothScroll = s.init(t(a.smoothScrollOptions, {callback: i.enableTocAnimation}))), this
                        }
                    }, u.refresh = function (e) {
                        u.destroy(), u.init(e || this.options)
                    }, e.tocbot = u, u
                })
            }).call(t, function () {
                return this
            }())
        },/*!******************************************************!*\
   !*** ./~/smooth-scroll/dist/js/smooth-scroll.min.js ***!
   \******************************************************/
        function (e, t, n) {
            var o, i, r;
            (function (n) {/*! smooth-scroll v10.0.1 | (c) 2016 Chris Ferdinandi | MIT License | http://github.com/cferdinandi/smooth-scroll */
                !function (n, l) {
                    i = [], o = l(n), r = "function" == typeof o ? o.apply(t, i) : o, !(void 0 !== r && (e.exports = r))
                }("undefined" != typeof n ? n : this.window || this.global, function (e) {
                    "use strict";
                    var t, n, o, i, r, l, s, c = {}, a = "querySelector" in document && "addEventListener" in e, u = {
                        selector: "[data-scroll]",
                        selectorHeader: null,
                        speed: 500,
                        easing: "easeInOutCubic",
                        offset: 0,
                        callback: function () {
                        }
                    }, d = function () {
                        var e = {}, t = !1, n = 0, o = arguments.length;
                        "[object Boolean]" === Object.prototype.toString.call(arguments[0]) && (t = arguments[0], n++);
                        for (var i = function (n) {
                            for (var o in n) Object.prototype.hasOwnProperty.call(n, o) && (t && "[object Object]" === Object.prototype.toString.call(n[o]) ? e[o] = d(!0, e[o], n[o]) : e[o] = n[o])
                        }; o > n; n++) {
                            var r = arguments[n];
                            i(r)
                        }
                        return e
                    }, f = function (e) {
                        return Math.max(e.scrollHeight, e.offsetHeight, e.clientHeight)
                    }, m = function (e, t) {
                        var n, o, i = t.charAt(0), r = "classList" in document.documentElement;
                        for ("[" === i && (t = t.substr(1, t.length - 2), n = t.split("="), n.length > 1 && (o = !0, n[1] = n[1].replace(/"/g, "").replace(/'/g, ""))); e && e !== document && 1 === e.nodeType; e = e.parentNode) {
                            if ("." === i) if (r) {
                                if (e.classList.contains(t.substr(1))) return e
                            } else if (new RegExp("(^|\\s)" + t.substr(1) + "(\\s|$)").test(e.className)) return e;
                            if ("#" === i && e.id === t.substr(1)) return e;
                            if ("[" === i && e.hasAttribute(n[0])) {
                                if (!o) return e;
                                if (e.getAttribute(n[0]) === n[1]) return e
                            }
                            if (e.tagName.toLowerCase() === t) return e
                        }
                        return null
                    }, h = function (e) {
                        "#" === e.charAt(0) && (e = e.substr(1));
                        for (var t, n = String(e), o = n.length, i = -1, r = "", l = n.charCodeAt(0); ++i < o;) {
                            if (t = n.charCodeAt(i), 0 === t) throw new InvalidCharacterError("Invalid character: the input contains U+0000.");
                            r += t >= 1 && 31 >= t || 127 == t || 0 === i && t >= 48 && 57 >= t || 1 === i && t >= 48 && 57 >= t && 45 === l ? "\\" + t.toString(16) + " " : t >= 128 || 45 === t || 95 === t || t >= 48 && 57 >= t || t >= 65 && 90 >= t || t >= 97 && 122 >= t ? n.charAt(i) : "\\" + n.charAt(i)
                        }
                        return "#" + r
                    }, p = function (e, t) {
                        var n;
                        return "easeInQuad" === e && (n = t * t), "easeOutQuad" === e && (n = t * (2 - t)), "easeInOutQuad" === e && (n = .5 > t ? 2 * t * t : -1 + (4 - 2 * t) * t), "easeInCubic" === e && (n = t * t * t), "easeOutCubic" === e && (n = --t * t * t + 1), "easeInOutCubic" === e && (n = .5 > t ? 4 * t * t * t : (t - 1) * (2 * t - 2) * (2 * t - 2) + 1), "easeInQuart" === e && (n = t * t * t * t), "easeOutQuart" === e && (n = 1 - --t * t * t * t), "easeInOutQuart" === e && (n = .5 > t ? 8 * t * t * t * t : 1 - 8 * --t * t * t * t), "easeInQuint" === e && (n = t * t * t * t * t), "easeOutQuint" === e && (n = 1 + --t * t * t * t * t), "easeInOutQuint" === e && (n = .5 > t ? 16 * t * t * t * t * t : 1 + 16 * --t * t * t * t * t), n || t
                    }, v = function (e, t, n) {
                        var o = 0;
                        if (e.offsetParent) do o += e.offsetTop, e = e.offsetParent; while (e);
                        return o = Math.max(o - t - n, 0), Math.min(o, b() - g())
                    }, g = function () {
                        return Math.max(document.documentElement.clientHeight, e.innerHeight || 0)
                    }, b = function () {
                        return Math.max(document.body.scrollHeight, document.documentElement.scrollHeight, document.body.offsetHeight, document.documentElement.offsetHeight, document.body.clientHeight, document.documentElement.clientHeight)
                    }, C = function (e) {
                        return e && "object" == typeof JSON && "function" == typeof JSON.parse ? JSON.parse(e) : {}
                    }, S = function (e) {
                        return e ? f(e) + e.offsetTop : 0
                    }, y = function (t, n, o) {
                        o || (t.focus(), document.activeElement.id !== t.id && (t.setAttribute("tabindex", "-1"), t.focus(), t.style.outline = "none"), e.scrollTo(0, n))
                    };
                    c.animateScroll = function (n, o, l) {
                        var c = C(o ? o.getAttribute("data-options") : null), a = d(t || u, l || {}, c),
                            f = "[object Number]" === Object.prototype.toString.call(n), m = f || !n.tagName ? null : n;
                        if (f || m) {
                            var h = e.pageYOffset;
                            a.selectorHeader && !i && (i = document.querySelector(a.selectorHeader)), r || (r = S(i));
                            var g, x, N = f ? n : v(m, r, parseInt(a.offset, 10)), L = N - h, O = b(), E = 0,
                                A = function (t, i, r) {
                                    var l = e.pageYOffset;
                                    (t == i || l == i || e.innerHeight + l >= O) && (clearInterval(r), y(n, i, f), a.callback(n, o))
                                }, H = function () {
                                    E += 16, g = E / parseInt(a.speed, 10), g = g > 1 ? 1 : g, x = h + L * p(a.easing, g), e.scrollTo(0, Math.floor(x)), A(x, N, s)
                                }, T = function () {
                                    clearInterval(s), s = setInterval(H, 16)
                                };
                            0 === e.pageYOffset && e.scrollTo(0, 0), T()
                        }
                    };
                    var x = function (t) {
                        e.location.hash, n && (n.id = n.getAttribute("data-scroll-id"), c.animateScroll(n, o), n = null, o = null)
                    }, N = function (i) {
                        if (0 === i.button && !i.metaKey && !i.ctrlKey && (o = m(i.target, t.selector), o && "a" === o.tagName.toLowerCase() && o.hostname === e.location.hostname && o.pathname === e.location.pathname && /#/.test(o.href))) {
                            var r = h(o.hash);
                            if ("#" === r) {
                                i.preventDefault(), n = document.body;
                                var l = n.id ? n.id : "smooth-scroll-top";
                                return n.setAttribute("data-scroll-id", l), n.id = "", void (e.location.hash.substring(1) === l ? x() : e.location.hash = l)
                            }
                            n = document.querySelector(r), n && (n.setAttribute("data-scroll-id", n.id), n.id = "", o.hash === e.location.hash && (i.preventDefault(), x()))
                        }
                    }, L = function (e) {
                        l || (l = setTimeout(function () {
                            l = null, r = S(i)
                        }, 66))
                    };
                    return c.destroy = function () {
                        t && (document.removeEventListener("click", N, !1), e.removeEventListener("resize", L, !1), t = null, n = null, o = null, i = null, r = null, l = null, s = null)
                    }, c.init = function (n) {
                        a && (c.destroy(), t = d(u, n || {}), i = t.selectorHeader ? document.querySelector(t.selectorHeader) : null, r = S(i), document.addEventListener("click", N, !1), e.addEventListener("hashchange", x, !1), i && e.addEventListener("resize", L, !1))
                    }, c
                })
            }).call(t, function () {
                return this
            }())
        },/*!***********************************!*\
   !*** ./src/js/default-options.js ***!
   \***********************************/
        function (e, t) {
            e.exports = {
                tocSelector: ".js-toc",
                contentSelector: ".js-toc-content",
                headingSelector: "h1, h2, h3",
                ignoreSelector: ".js-toc-ignore",
                linkClass: "toc-link",
                extraLinkClasses: "",
                activeLinkClass: "is-active-link",
                listClass: "toc-list",
                extraListClasses: "",
                isCollapsedClass: "is-collapsed",
                collapsibleClass: "is-collapsible",
                listItemClass: "toc-list-item",
                collapseDepth: 0,
                smoothScrollOptions: {easing: "easeInOutCubic", offset: 0, speed: 300, updateURL: !0},
                headingsOffset: 0,
                throttleTimeout: 50,
                positionFixedSelector: null,
                positionFixedClass: "is-position-fixed",
                fixedSidebarOffset: "auto",
                includeHtml: !1
            }
        },/*!******************************!*\
   !*** ./src/js/build-html.js ***!
   \******************************/
        function (e, t) {
            e.exports = function (e) {
                function t(e, n) {
                    var r = n.appendChild(o(e));
                    if (e.children.length) {
                        var l = i(e.isCollapsed);
                        e.children.forEach(function (e) {
                            t(e, l)
                        }), r.appendChild(l)
                    }
                }

                function n(e, n) {
                    var o = !1, r = i(o);
                    n.forEach(function (e) {
                        t(e, r)
                    });
                    var l = document.querySelector(e);
                    if (null !== l) return l.firstChild && l.removeChild(l.firstChild), l.appendChild(r)
                }

                function o(t) {
                    var n = document.createElement("li"), o = document.createElement("a");
                    return e.listItemClass && n.setAttribute("class", e.listItemClass), e.includeHtml && t.childNodes.length ? u.call(t.childNodes, function (e) {
                        o.appendChild(e.cloneNode(!0))
                    }) : o.textContent = t.textContent, o.setAttribute("data-scroll", ""), o.setAttribute("href", "#" + t.id), o.setAttribute("class", e.linkClass + h + "node-name--" + t.nodeName + h + e.extraLinkClasses), n.appendChild(o), n
                }

                function i(t) {
                    var n = document.createElement("ul"), o = e.listClass + h + e.extraListClasses;
                    return t && (o += h + e.collapsibleClass, o += h + e.isCollapsedClass), n.setAttribute("class", o), n
                }

                function r() {
                    var t = document.documentElement.scrollTop || f.scrollTop,
                        n = document.querySelector(e.positionFixedSelector);
                    "auto" === e.fixedSidebarOffset && (e.fixedSidebarOffset = document.querySelector(e.tocSelector).offsetTop), t > e.fixedSidebarOffset ? n.className.indexOf(e.positionFixedClass) === -1 && (n.className += h + e.positionFixedClass) : n.className = n.className.split(h + e.positionFixedClass).join("")
                }

                function l(t) {
                    var n = document.documentElement.scrollTop || f.scrollTop;
                    e.positionFixedSelector && r();
                    var o, i = t;
                    if (m && null !== document.querySelector(e.tocSelector) && i.length > 0) {
                        d.call(i, function (t, r) {
                            if (t.offsetTop > n + e.headingsOffset) {
                                var l = 0 === r ? r : r - 1;
                                return o = i[l], !0
                            }
                            if (r === i.length - 1) return o = i[i.length - 1], !0
                        });
                        var l = document.querySelector(e.tocSelector).querySelectorAll("." + e.linkClass);
                        u.call(l, function (t) {
                            t.className = t.className.split(h + e.activeLinkClass).join("")
                        });
                        var c = document.querySelector(e.tocSelector).querySelector("." + e.linkClass + ".node-name--" + o.nodeName + '[href="#' + o.id + '"]');
                        c.className += h + e.activeLinkClass;
                        var a = document.querySelector(e.tocSelector).querySelectorAll("." + e.listClass + "." + e.collapsibleClass);
                        u.call(a, function (t) {
                            var n = h + e.isCollapsedClass;
                            t.className.indexOf(n) === -1 && (t.className += h + e.isCollapsedClass)
                        }), c.nextSibling && (c.nextSibling.className = c.nextSibling.className.split(h + e.isCollapsedClass).join("")), s(c.parentNode.parentNode)
                    }
                }

                function s(t) {
                    return t.className.indexOf(e.collapsibleClass) !== -1 ? (t.className = t.className.split(h + e.isCollapsedClass).join(""), s(t.parentNode.parentNode)) : t
                }

                function c(t) {
                    var n = t.target || t.srcElement;
                    n.className.indexOf(e.linkClass) !== -1 && (m = !1)
                }

                function a() {
                    m = !0
                }

                var u = [].forEach, d = [].some, f = document.body, m = !0, h = " ";
                return {enableTocAnimation: a, disableTocAnimation: c, render: n, updateToc: l}
            }
        },/*!*********************************!*\
   !*** ./src/js/parse-content.js ***!
   \*********************************/
        function (e, t) {
            e.exports = function (e) {
                function t(e) {
                    return e[e.length - 1]
                }

                function n(e) {
                    return +e.nodeName.split("H").join("")
                }

                function o(t) {
                    var o = {
                        id: t.id,
                        children: [],
                        nodeName: t.nodeName,
                        headingLevel: n(t),
                        textContent: t.textContent.trim()
                    };
                    return e.includeHtml && (o.childNodes = t.childNodes), o
                }

                function i(i, r) {
                    for (var l = o(i), s = n(i), c = r, a = t(c), u = a ? a.headingLevel : 0, d = s - u; d > 0;) a = t(c), a && void 0 !== a.children && (c = a.children), d--;
                    return s >= e.collapseDepth && (l.isCollapsed = !0), c.push(l), c
                }

                function r(t, n) {
                    var o = n;
                    e.ignoreSelector && (o = n.split(",").map(function (t) {
                        return t.trim() + ":not(" + e.ignoreSelector + ")"
                    }));
                    try {
                        return document.querySelector(t).querySelectorAll(o)
                    } catch (i) {
                        return console.warn("Element not found: " + t), null
                    }
                }

                function l(e) {
                    return s.call(e, function (e, t) {
                        var n = o(t);
                        return i(n, e.nest), e
                    }, {nest: []})
                }

                var s = [].reduce;
                return {nestHeadingsArray: l, selectHeadings: r}
            }
        }]);
    //# sourceMappingURL=tocbot.min.js.map

</script>

<script type="text/javascript">

    var generateToc = function () {
        var readyState = document.readyState;
        if (readyState === 'interactive' || readyState == 'complete') {

            var headerSize = 140;

            var tocParentNode = document.createElement("div");
            tocParentNode.setAttribute("id", "toc-parent");

            var generatedTocNode = document.createElement("div");
            generatedTocNode.setAttribute("id", "generated-toc");
            tocParentNode.appendChild(generatedTocNode);

            var contentNode = document.getElementById("content");
            contentNode.parentNode.insertBefore(tocParentNode, contentNode);

            var clearNode = document.createElement("div");
            clearNode.setAttribute("class", "clear");
            contentNode.parentNode.appendChild(clearNode);

            tocbot.init({
                tocSelector: '#generated-toc',
                contentSelector: '#content',
                headingSelector: 'h2, h3, h4, h5',
                headingsOffset: headerSize,
                smoothScrollOptions: {
                    easing: 'easeInOutCubic',
                    offset: headerSize,
                    speed: 300, // animation duration.
                    updateURL: true
                },
                collapseDepth: 0
            });

        } else {
            window.setTimeout(function () {
                generateToc();
            }, 50);
        }

    }
    generateToc();

</script>

<div class="choose-version">
    <select id="choose-version" onchange="chooseVersion(this.value)">
        <option value="6.8.0">6.8.0</option>
        <option value="7.1.0">7.1.0</option>
    </select>
</div>

<script type="text/javascript">
    var initVersion = function () {
        var list = window.location.pathname.split('/');
        document.getElementById('choose-version').value = list[list.length - 2];
    };
    initVersion();

    var chooseVersion = function (obj) {
        window.location.href = '../' + obj;
    }
</script>
</head>
<body id="java-api" class="book">
<div id="header">
<h1>ElasticSearch Java API v6.8.0 (初稿)</h1>
</div>
<div id="content">
<div class="sect1">
<h2 id="preface">1. 前言</h2>
<div class="sectionbody">
<div class="paragraph">
<p>本节介绍由Elasticsearch提供的Java API。
所有的Elasticsearch操作都使用 <a href="#client">Client</a> 对象来执行。
所有操作默认就是异步的（可以使用listener监听，也可以直接返回结果）。</p>
</div>
<div class="paragraph">
<p>此外，也可以使用 <a href="#java-docs-bulk">Bulk</a> 在client中批量的执行一系列操作。</p>
</div>
<div class="paragraph">
<p>请注意，所有的API都是通过Java API调用的（实际上，内部也是使用Java API执行的）</p>
</div>
<div class="admonitionblock warning">
<table>
<tr>
<td class="icon">
<i class="fa icon-warning" title="Warning"></i>
</td>
<td class="content">
<div class="paragraph">
<p>我们计划在ElasticSearch 7.0中弃用 <code>TransportClient</code> ，并在8.0中完全删除它。
作为替代，您应该使用 <a href="https://www.elastic.co/guide/en/elasticsearch/client/java-rest/6.8/java-rest-high.html">Java High Level REST Client</a> ，
它执行的是HTTP请求而不是序列化之后的Java请求。
<a href="https://www.elastic.co/guide/en/elasticsearch/client/java-rest/6.8/java-rest-high-level-migration.html">迁移指南</a> 中介绍了迁移所需的所有步骤。</p>
</div>
<div class="paragraph">
<p>JavaHighLevelClient 现在支持了更多常用的接口，但还有许多需要添加。
点击 <a href="https://github.com/elastic/elasticsearch/issues/27205">完善 Java high-level REST client</a>
通知我们您的应用需要哪些缺失的接口，帮助我们共同完善Elasticsearch。</p>
</div>
<div class="paragraph">
<p>所有缺失的接口也可以通过使用带有JSON请求体的
<a href="https://www.elastic.co/guide/en/elasticsearch/client/java-rest/6.8/java-rest-low.html">low level Java REST Client</a>
来实现并获取结果。</p>
</div>
</td>
</tr>
</table>
</div>
</div>
</div>
<div class="sect1">
<h2 id="java-doc">2. Javadoc</h2>
<div class="sectionbody">
<div class="paragraph">
<p>TransClient 的Javadoc可以在 <a href="https://artifacts.elastic.co/javadoc/org/elasticsearch/client/transport/6.8.0/index.html">这里</a> 找到。</p>
</div>
</div>
</div>
<div class="sect1">
<h2 id="maven-repository">3. Maven仓库</h2>
<div class="sectionbody">
<div class="paragraph">
<p>ElasticSearch已经托管在 <a href="http://search.maven.org/#search%7Cga%7C1%7Cg%3A%22org.elasticsearch.client%22">Maven Central</a> 上。</p>
</div>
<div class="paragraph">
<p>举个例子，您可以这样在 <code>pom.xml</code> 文件中定义最新版本：</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-xml" data-lang="xml">&lt;dependency&gt;
    &lt;groupId&gt;org.elasticsearch&lt;/groupId&gt;
    &lt;artifactId&gt;elasticsearch&lt;/artifactId&gt;
    &lt;version&gt;{version}&lt;/version&gt;
&lt;/dependency&gt;</code></pre>
</div>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-xml" data-lang="xml">&lt;dependency&gt;
    &lt;groupId&gt;org.elasticsearch.client&lt;/groupId&gt;
    &lt;artifactId&gt;transport&lt;/artifactId&gt;
    &lt;version&gt;{version}&lt;/version&gt;
&lt;/dependency&gt;</code></pre>
</div>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-xml" data-lang="xml">&lt;dependency&gt;
    &lt;groupId&gt;org.elasticsearch.client&lt;/groupId&gt;
    &lt;artifactId&gt;elasticsearch-rest-high-level-client&lt;/artifactId&gt;
    &lt;version&gt;{version}&lt;/version&gt;
&lt;/dependency&gt;</code></pre>
</div>
</div>
<div class="sect2">
<h3 id="java-transport-usage-maven-lucene">3.1. Lucene Snapshot 仓库</h3>
<div class="paragraph">
<p>有时候主要版本(如beta版)的第一个版本可能建立在Lucene的快照版本之上，这时候您可能无法解决Lucene的依赖问题。</p>
</div>
<div class="paragraph">
<p>例如，如果您使用的是Elasticsearch <code>6.0.0-beta1</code> 版本，它依赖的是 <code>7.0.0-snapshot-00142c9</code> 版本的Lucene，这时候就需要定义以下仓库.</p>
</div>
<div class="paragraph">
<p>对于 Maven:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-xml" data-lang="xml">&lt;repository&gt;
    &lt;id&gt;elastic-lucene-snapshots&lt;/id&gt;
    &lt;name&gt;Elastic Lucene Snapshots&lt;/name&gt;
    &lt;url&gt;https://s3.amazonaws.com/download.elasticsearch.org/lucenesnapshots/00142c9&lt;/url&gt;
    &lt;releases&gt;&lt;enabled&gt;true&lt;/enabled&gt;&lt;/releases&gt;
    &lt;snapshots&gt;&lt;enabled&gt;false&lt;/enabled&gt;&lt;/snapshots&gt;
&lt;/repository&gt;</code></pre>
</div>
</div>
<div class="paragraph">
<p>对于 Gradle:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-groovy" data-lang="groovy">maven {
    name "lucene-snapshots"
    url 'https://s3.amazonaws.com/download.elasticsearch.org/lucenesnapshots/00142c9'
}</code></pre>
</div>
</div>
</div>
<div class="sect2">
<h3 id="log4j-2">3.2. Log4j 2 日志</h3>
<div class="paragraph">
<p>你需要加入log4j2的依赖:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-xml" data-lang="xml">&lt;dependency&gt;
    &lt;groupId&gt;org.apache.logging.log4j&lt;/groupId&gt;
    &lt;artifactId&gt;log4j-core&lt;/artifactId&gt;
    &lt;version&gt;2.11.1&lt;/version&gt;
&lt;/dependency&gt;</code></pre>
</div>
</div>
<div class="paragraph">
<p>加入log4j2的配置文件。
举个例子，你可以在项目中的 <code>src/main/resources</code> 目录加入 <code>log4j2.properties</code> 文件，示例内容如下：</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-properties" data-lang="properties">appender.console.type = Console
appender.console.name = console
appender.console.layout.type = PatternLayout
appender.console.layout.pattern = [%d{ISO8601}][%-5p][%-25c] %marker%m%n

rootLogger.level = info
rootLogger.appenderRef.console.ref = console</code></pre>
</div>
</div>
</div>
<div class="sect2">
<h3 id="use-other-log">3.3. 使用其它的日志</h3>
<div class="paragraph">
<p>如果您想使用其它日志而不是log4j2，则可以用 <a href="http://www.slf4j.org/">SLF4J</a> 规范下的实现来代替:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-xml" data-lang="xml">&lt;dependency&gt;
    &lt;groupId&gt;org.apache.logging.log4j&lt;/groupId&gt;
    &lt;artifactId&gt;log4j-to-slf4j&lt;/artifactId&gt;
    &lt;version&gt;2.11.1&lt;/version&gt;
&lt;/dependency&gt;
&lt;dependency&gt;
    &lt;groupId&gt;org.slf4j&lt;/groupId&gt;
    &lt;artifactId&gt;slf4j-api&lt;/artifactId&gt;
    &lt;version&gt;1.7.24&lt;/version&gt;
&lt;/dependency&gt;</code></pre>
</div>
</div>
<div class="paragraph">
<p><a href="http://www.slf4j.org/manual.html">这个页面</a> 列出了可以使用的实现。
选择你喜欢的日志添加依赖即可。
举个例子我想使用 <code>slf4j-simple</code> 日志就可以添加如下依赖:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-xml" data-lang="xml">&lt;dependency&gt;
    &lt;groupId&gt;org.slf4j&lt;/groupId&gt;
    &lt;artifactId&gt;slf4j-simple&lt;/artifactId&gt;
    &lt;version&gt;1.7.21&lt;/version&gt;
&lt;/dependency&gt;</code></pre>
</div>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="client">4. Client</h2>
<div class="sectionbody">
<div class="paragraph">
<p>有很多种使用 <strong>Java client</strong> 的方式供你选择:</p>
</div>
<div class="ulist">
<ul>
<li>
<p>在集群中执行标准的 <a href="#java-docs-index">index</a>, <a href="#java-docs-get">get</a>,
<a href="#java-docs-delete">delete</a> 和 <a href="#java-search">search</a> 操作</p>
</li>
<li>
<p>在运行中的集群下执行管理员任务</p>
</li>
</ul>
</div>
<div class="paragraph">
<p>在Elasticsearch中获取 <code>Client</code> 很简单。
最常用的方法就是创建一个 <a href="#transport-client"><code>TransportClient</code></a> 连接到集群中，并获取client。</p>
</div>
<div class="admonitionblock important">
<table>
<tr>
<td class="icon">
<i class="fa icon-important" title="Important"></i>
</td>
<td class="content">
<div class="paragraph">
<p>所有集群中的client节点必须使用相同的major版本(例如 <code>2.x</code> 或 <code>5.x</code>)。
但是不同minor版本的client却都可以连接到集群，只是有些新版本的特性在旧版本下可能会不支持。
所以最理想的状态就是集群中所有client的版本号都相同。</p>
</div>
</td>
</tr>
</table>
</div>
<div class="admonitionblock warning">
<table>
<tr>
<td class="icon">
<i class="fa icon-warning" title="Warning"></i>
</td>
<td class="content">
<div class="paragraph">
<p>我们计划在ElasticSearch 7.0中弃用 <code>TransportClient</code> ，并在8.0中完全删除它。
作为替代，您应该使用 <a href="https://www.elastic.co/guide/en/elasticsearch/client/java-rest/6.8/java-rest-high.html">Java High Level REST Client</a> ，
它执行的是HTTP请求而不是序列化之后的Java请求。
<a href="https://www.elastic.co/guide/en/elasticsearch/client/java-rest/6.8/java-rest-high-level-migration.html">迁移指南</a> 中介绍了迁移所需的所有步骤。</p>
</div>
<div class="paragraph">
<p>JavaHighLevelClient 现在支持了更多常用的接口，但还有许多需要添加。
点击 <a href="https://github.com/elastic/elasticsearch/issues/27205">完善 Java high-level REST client</a>
通知我们您的应用需要哪些缺失的接口，帮助我们共同完善Elasticsearch。</p>
</div>
<div class="paragraph">
<p>所有缺失的接口也可以通过使用带有JSON请求体的
<a href="https://www.elastic.co/guide/en/elasticsearch/client/java-rest/6.8/java-rest-low.html">low level Java REST Client</a>
来实现并获取结果。</p>
</div>
</td>
</tr>
</table>
</div>
<div class="sect2">
<h3 id="transport-client">4.1. Transport Client</h3>
<div class="paragraph">
<p><code>TransportClient</code> 使用 transport模块远程连接到Elasticsearch集群。
它并不是加入到集群中，而只是获取一个或多个初始传输地址，在操作的时候以循环的方式与之进行通信(大部分操作可能都是 "two hop" 操作):</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java">// on startup

TransportClient client = new PreBuiltTransportClient(Settings.EMPTY)
        .addTransportAddress(new TransportAddress(InetAddress.getByName("host1"), 9300))
        .addTransportAddress(new TransportAddress(InetAddress.getByName("host2"), 9300));

// on shutdown

client.close();</code></pre>
</div>
</div>
<div class="paragraph">
<p>注意如果你的集群名称不是 "elasticsearch" 的话，你需要设置成你自己的:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java">Settings settings = Settings.builder()
        .put("cluster.name", "myClusterName").build();
TransportClient client = new PreBuiltTransportClient(settings);
//Add transport addresses and do something with the client...</code></pre>
</div>
</div>
<div class="paragraph">
<p>Transport client 具有集群感知的特性，可以自动添加新主机或者是删除旧主机。
当感知被开启时，transport client 通过调用 <code>addTransportAddress</code> 方法与内部节点列表中的某一个节点建立连接。
在这之后，这个 client 就可以调用节点内部的API来获取数据了。
客户端内部的节点列表会替换这些数据节点，列表默认情况下每5秒刷新一次。
注意感知所连接的ip地址可以声明在 Elasticsearch 的配置文件中。</p>
</div>
<div class="paragraph">
<p>请记住，如果连接到的不是数据节点，那么这个节点列表可能不会包含它的原始节点。
例如，你初始化并连接到了一个master节点，在感知之后，接下来的请求都不会发送到这个master节点，而是发送到其它的数据节点。
transport client排除非数据节点的原因，是为了避免向master节点发送搜索请求。</p>
</div>
<div class="paragraph">
<p>想允许感知特性，请设置 <code>client.transport.sniff</code> 为 <code>true</code> :</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java">Settings settings = Settings.builder()
        .put("client.transport.sniff", true).build();
TransportClient client = new PreBuiltTransportClient(settings);</code></pre>
</div>
</div>
<div class="paragraph">
<p>其它 transport client 级别的设置包括:</p>
</div>
<table class="tableblock frame-all grid-all stretch">
<colgroup>
<col style="width: 50%;">
<col style="width: 50%;">
</colgroup>
<thead>
<tr>
<th class="tableblock halign-left valign-top">参数</th>
<th class="tableblock halign-left valign-top">描述</th>
</tr>
</thead>
<tbody>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><code>client.transport.ignore_cluster_name</code></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">设置成 <code>true</code> 会所连接节点的集群名称校验(0.19.4+)</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><code>client.transport.ping_timeout</code></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">ping节点的超时时间。默认是 <code>5秒</code>。</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><code>client.transport.nodes_sampler_interval</code></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">多长时间 sample / ping 节点列表和连接。默认是 <code>5秒</code>。</p></td>
</tr>
</tbody>
</table>
</div>
<div class="sect2">
<h3 id="client-connected-to-client-node">4.2. 将 Client 连接到一个协调节点</h3>
<div class="paragraph">
<p>你可以在本地开启一个
<a href="https://www.elastic.co/guide/en/elasticsearch/reference/6.8/modules-node.html#coordinating-only-node">协调节点</a>
，然后在连接到该协调节点的应用中轻松地创建一个 <a href="#transport-client"><code>TransportClient</code></a> 。</p>
</div>
<div class="paragraph">
<p>这样这个协调节点就能够加载你需要的所有插件了（例如 discovery 插件）。</p>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="java-docs">5. 文档 API</h2>
<div class="sectionbody">
<div class="paragraph">
<p>这部分讲的是这些CRUD API:</p>
</div>
<div class="ulist">
<div class="title">单文档 API</div>
<ul>
<li>
<p><a href="#java-docs-index">对JSON文档建立索引</a></p>
</li>
<li>
<p><a href="#java-docs-get">根据ID获取文档</a></p>
</li>
<li>
<p><a href="#java-docs-delete">删除文档</a></p>
</li>
<li>
<p><a href="#java-docs-update">更新文档</a></p>
</li>
</ul>
</div>
<div class="ulist">
<div class="title">多文档 API</div>
<ul>
<li>
<p><a href="#java-docs-multi-get">获取多个文档</a></p>
</li>
<li>
<p><a href="#java-docs-bulk">批处理</a></p>
</li>
<li>
<p><a href="#java-docs-reindex">重新建立索引</a></p>
</li>
<li>
<p><a href="#java-docs-update-by-query">通过条件更新文档</a></p>
</li>
<li>
<p><a href="#java-docs-delete-by-query">根据条件删除文档</a></p>
</li>
</ul>
</div>
<div class="admonitionblock note">
<table>
<tr>
<td class="icon">
<i class="fa icon-note" title="Note"></i>
</td>
<td class="content">
所有的CRUD API 都是单index API。 <code>index</code> 参数只可以接受单独的index，或者是使用 <code>alias</code> 来指向这个index。
</td>
</tr>
</table>
</div>
<div class="sect2">
<h3 id="java-docs-index">5.1. 对JSON文档建立索引</h3>
<div class="paragraph">
<p>Index API 可以在指定的index中将一个结构化的JSON文档建立索引，并使其可以被查询到。</p>
</div>
<div class="sect3">
<h4 id="java-docs-index-generate">5.1.1. 生成JSON格式的文档</h4>
<div class="paragraph">
<p>一般有下面几种方式来生成一个JSON文档:</p>
</div>
<div class="ulist">
<ul>
<li>
<p>手动使用 <code>byte[]</code> 或 <code>String</code> 类型拼接一个JSON</p>
</li>
<li>
<p>使用 <code>Map</code> 类型会自动转换成对应的JSON</p>
</li>
<li>
<p>使用第三方库将你的Bean序列化成Json格式，例如 <a href="https://github.com/FasterXML/jackson">Jackson</a> 库等</p>
</li>
<li>
<p>使用内置的 XContentFactory.jsonBuilder() 生成JSON</p>
</li>
</ul>
</div>
<div class="paragraph">
<p>在内部，所有类型最终都会转换成 <code>byte[]</code> 类型（所以String类型最后也会转成 <code>byte[]</code> 类型）。
因此，如果你的对象已经是 <code>byte[]</code> 类型了，那么就直接使用它吧。
当然官方内置的 <code>jsonBuilder</code> 是一个高度优化后的工具，你可以使用它来直接构造 <code>byte[]</code> 。</p>
</div>
<div class="sect4">
<h5 id="java-docs-index-generate-diy">手动拼接</h5>
<div class="paragraph">
<p>没什么困难的，唯一需要注意的是通过
<a href="https://www.elastic.co/guide/en/elasticsearch/reference/6.8/mapping-date-format.html">Date Format</a>
对日期进行格式化。</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java">String json = "{" +
        "\"user\":\"kimchy\"," +
        "\"postDate\":\"2013-01-30\"," +
        "\"message\":\"trying out Elasticsearch\"" +
    "}";</code></pre>
</div>
</div>
</div>
<div class="sect4">
<h5 id="java-docs-index-generate-using-map">使用 Map</h5>
<div class="paragraph">
<p>Map是一个键值对的集合，它可以等价于一个JSON结构:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java">Map&lt;String, Object&gt; json = new HashMap&lt;String, Object&gt;();
json.put("user","kimchy");
json.put("postDate",new Date());
json.put("message","trying out Elasticsearch");</code></pre>
</div>
</div>
</div>
<div class="sect4">
<h5 id="java-docs-index-generate-beans">序列化 JavaBean</h5>
<div class="paragraph">
<p>你可以使用 <a href="https://github.com/FasterXML/jackson">Jackson</a> 将你的Bean序列化成JSON。
请将 <a href="http://search.maven.org/#search%7Cga%7C1%7Cjackson-databind">Jackson Databind</a> 加入你的项目中。
然后你就可以使用 <code>ObjectMapper</code> 来序列化你的Bean了:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java">import com.fasterxml.jackson.databind.*;

// 实例化一个 json mapper
ObjectMapper mapper = new ObjectMapper(); // 只创建一次，重复使用

// 生成 json
byte[] json = mapper.writeValueAsBytes(yourbeaninstance);</code></pre>
</div>
</div>
</div>
<div class="sect4">
<h5 id="java-docs-index-generate-helpers">使用 Elasticsearch 助手</h5>
<div class="paragraph">
<p>Elasticsearch 提供了一个内置的助手来帮助你生成JSON内容。</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java">import static org.elasticsearch.common.xcontent.XContentFactory.*;

XContentBuilder builder = jsonBuilder()
    .startObject()
        .field("user", "kimchy")
        .field("postDate", new Date())
        .field("message", "trying out Elasticsearch")
    .endObject()</code></pre>
</div>
</div>
<div class="paragraph">
<p>注意，你也可以使用 <code>startArray(String)</code> 和 <code>endArray()</code> 方法来添加一个数组。
顺便说一下，<code>field</code> 方法可以接受很多对象类型。
你可以直接传一些 number，date 或者是其它 XContentBuilder 对象。</p>
</div>
<div class="paragraph">
<p>如果你想查看生成的JSON内容，可以使用 <code>Strings.toString()</code> 方法。</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java">import org.elasticsearch.common.Strings;

String json = Strings.toString(builder);</code></pre>
</div>
</div>
</div>
</div>
<div class="sect3">
<h4 id="java-docs-index-doc">5.1.2. 对文档建立索引</h4>
<div class="paragraph">
<p>下面就是将一个JSON文档建立索引的例子，其中index为twitter，type为 <code>_doc</code> ，id的值是1:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java">import static org.elasticsearch.common.xcontent.XContentFactory.*;

IndexResponse response = client.prepareIndex("twitter", "_doc", "1")
        .setSource(jsonBuilder()
                    .startObject()
                        .field("user", "kimchy")
                        .field("postDate", new Date())
                        .field("message", "trying out Elasticsearch")
                    .endObject()
                  )
        .get();</code></pre>
</div>
</div>
<div class="paragraph">
<p>注意，你也可以对一个JSON字符串类型的文档建立索引，并且 ID 也不是必须的:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java">String json = "{" +
        "\"user\":\"kimchy\"," +
        "\"postDate\":\"2013-01-30\"," +
        "\"message\":\"trying out Elasticsearch\"" +
    "}";

IndexResponse response = client.prepareIndex("twitter", "_doc")
        .setSource(json, XContentType.JSON)
        .get();</code></pre>
</div>
</div>
<div class="paragraph">
<p>结果可以在 <code>IndexResponse</code> 中查看:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java">// Index 名称
String _index = response.getIndex();
// Type 名称
String _type = response.getType();
// Document ID (generated or not)
String _id = response.getId();
// Version (如果你是新建的这个文档，会得到1)
long _version = response.getVersion();
// 当前实例的存储状态
RestStatus status = response.status();</code></pre>
</div>
</div>
<div class="paragraph">
<p>有关index操作的更多信息，请查看 REST <a href="https://www.elastic.co/guide/en/elasticsearch/reference/6.8/docs-index_.html">index</a> 。</p>
</div>
</div>
</div>
<div class="sect2">
<h3 id="java-docs-get">5.2. 根据ID获取文档</h3>
<div class="paragraph">
<p>Get API 可以根据 <code>id</code> 从 index 中获取JSON文档。
下面就是一个获取JSON格式文档的例子，它的条件是index为twitter，type是 <code>_doc</code> ，id是1:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java">GetResponse response = client.prepareGet("twitter", "_doc", "1").get();</code></pre>
</div>
</div>
<div class="paragraph">
<p>有关Get操作的更多信息，请查看 REST <a href="https://www.elastic.co/guide/en/elasticsearch/reference/6.8/docs-get.html">get</a> 。</p>
</div>
</div>
<div class="sect2">
<h3 id="java-docs-delete">5.3. 删除文档</h3>
<div class="paragraph">
<p>Delete API 可以在指定的 index 中根据ID删除一个JSON类型的文档。
下面就是一个删除JSON文档的例子，它的index是twitter，type是 <code>_doc</code> ，id是1:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java">DeleteResponse response = client.prepareDelete("twitter", "_doc", "1").get();</code></pre>
</div>
</div>
<div class="paragraph">
<p>有关Delete操作的更多信息，请查看 <a href="https://www.elastic.co/guide/en/elasticsearch/reference/6.8/docs-delete.html">delete API</a> 。</p>
</div>
</div>
<div class="sect2">
<h3 id="java-docs-delete-by-query">5.4. 根据条件删除文档</h3>
<div class="paragraph">
<p>Delete By Query API 可以根据查询的结果删除一组文档:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java">BulkByScrollResponse response =
  DeleteByQueryAction.INSTANCE.newRequestBuilder(client)
    .filter(QueryBuilders.matchQuery("gender", "male")) <i class="conum" data-value="1"></i><b>(1)</b>
    .source("persons") <i class="conum" data-value="2"></i><b>(2)</b>
    .get(); <i class="conum" data-value="3"></i><b>(3)</b>
long deleted = response.getDeleted(); <i class="conum" data-value="4"></i><b>(4)</b></code></pre>
</div>
</div>
<div class="colist arabic">
<table>
<tr>
<td><i class="conum" data-value="1"></i><b>1</b></td>
<td>query</td>
</tr>
<tr>
<td><i class="conum" data-value="2"></i><b>2</b></td>
<td>index</td>
</tr>
<tr>
<td><i class="conum" data-value="3"></i><b>3</b></td>
<td>执行操作</td>
</tr>
<tr>
<td><i class="conum" data-value="4"></i><b>4</b></td>
<td>删除文档的数量</td>
</tr>
</table>
</div>
<div class="paragraph">
<p>由于这个操作可能会运行很长时间，如果你希望异步执行，可以使用 <code>execute</code> 代替 <code>get</code> 来执行，并提供一个listener，比如:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java">DeleteByQueryAction.INSTANCE.newRequestBuilder(client)
    .filter(QueryBuilders.matchQuery("gender", "male")) <i class="conum" data-value="1"></i><b>(1)</b>
    .source("persons") <i class="conum" data-value="2"></i><b>(2)</b>
    .execute(new ActionListener&lt;BulkByScrollResponse&gt;() { <i class="conum" data-value="3"></i><b>(3)</b>
        @Override
        public void onResponse(BulkByScrollResponse response) {
            long deleted = response.getDeleted(); <i class="conum" data-value="4"></i><b>(4)</b>
        }
        @Override
        public void onFailure(Exception e) {
            // Handle the exception
        }
    });</code></pre>
</div>
</div>
<div class="colist arabic">
<table>
<tr>
<td><i class="conum" data-value="1"></i><b>1</b></td>
<td>query</td>
</tr>
<tr>
<td><i class="conum" data-value="2"></i><b>2</b></td>
<td>index</td>
</tr>
<tr>
<td><i class="conum" data-value="3"></i><b>3</b></td>
<td>执行操作</td>
</tr>
<tr>
<td><i class="conum" data-value="4"></i><b>4</b></td>
<td>删除文档的数量</td>
</tr>
</table>
</div>
</div>
<div class="sect2">
<h3 id="java-docs-update">5.5. 更新文档</h3>
<div class="paragraph">
<p>你可以创建一个 <code>UpdateRequest</code> 并发送给client:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java">UpdateRequest updateRequest = new UpdateRequest();
updateRequest.index("index");
updateRequest.type("_doc");
updateRequest.id("1");
updateRequest.doc(jsonBuilder()
        .startObject()
            .field("gender", "male")
        .endObject());
client.update(updateRequest).get();</code></pre>
</div>
</div>
<div class="paragraph">
<p>或者也可以使用 <code>prepareUpdate()</code> 方法:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java">client.prepareUpdate("ttl", "doc", "1")
        .setScript(new Script(
            "ctx._source.gender = \"male\"", <i class="conum" data-value="1"></i><b>(1)</b>
            ScriptService.ScriptType.INLINE, null, null))
        .get();

client.prepareUpdate("ttl", "doc", "1")
        .setDoc(jsonBuilder() <i class="conum" data-value="2"></i><b>(2)</b>
            .startObject()
                .field("gender", "male")
            .endObject())
        .get();</code></pre>
</div>
</div>
<div class="colist arabic">
<table>
<tr>
<td><i class="conum" data-value="1"></i><b>1</b></td>
<td>你的脚本。它也可以是存储中本地文件中，这种情况下，需要使用 <code>ScriptService.ScriptType.FILE</code></td>
</tr>
<tr>
<td><i class="conum" data-value="2"></i><b>2</b></td>
<td>将要和已有文档合并的文档。</td>
</tr>
</table>
</div>
<div class="paragraph">
<p>Note that you can&#8217;t provide both <code>script</code> and <code>doc</code>.</p>
</div>
<div class="sect3">
<h4 id="java-docs-update-api-script">5.5.1. 通过脚本更新</h4>
<div class="paragraph">
<p>Update API 允许通过一个脚本来更新文档:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java">UpdateRequest updateRequest = new UpdateRequest("ttl", "doc", "1")
        .script(new Script("ctx._source.gender = \"male\""));
client.update(updateRequest).get();</code></pre>
</div>
</div>
</div>
<div class="sect3">
<h4 id="java-docs-update-api-merge-docs">5.5.2. 合并文档</h4>
<div class="paragraph">
<p>Update API 也可以传入一部分文档，并将之合并(简单的递归合并，对象的内部合并，替换键值对和数组)到一个已存在的文档中。
例如:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java">UpdateRequest updateRequest = new UpdateRequest("index", "type", "1")
        .doc(jsonBuilder()
            .startObject()
                .field("gender", "male")
            .endObject());
client.update(updateRequest).get();</code></pre>
</div>
</div>
</div>
<div class="sect3">
<h4 id="java-docs-update-api-upsert">5.5.3. 更新并插入</h4>
<div class="paragraph">
<p>Update API 也支持 <code>upsert</code> 。如果该文档不存在，则会对该文档建立索引:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java">IndexRequest indexRequest = new IndexRequest("index", "type", "1")
        .source(jsonBuilder()
            .startObject()
                .field("name", "Joe Smith")
                .field("gender", "male")
            .endObject());
UpdateRequest updateRequest = new UpdateRequest("index", "type", "1")
        .doc(jsonBuilder()
            .startObject()
                .field("gender", "male")
            .endObject())
        .upsert(indexRequest); <i class="conum" data-value="1"></i><b>(1)</b>
client.update(updateRequest).get();</code></pre>
</div>
</div>
<div class="colist arabic">
<table>
<tr>
<td><i class="conum" data-value="1"></i><b>1</b></td>
<td>如果文档不存在， <code>indexRequest</code> 中的元素就会被建立索引</td>
</tr>
</table>
</div>
<div class="paragraph">
<p>如果 <code>index/_doc/1</code> 这个文档已经存在了，在这个操作之后我们会有一个这样的文档:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-js" data-lang="js">{
    "name"  : "Joe Dalton",
    "gender": "male" <i class="conum" data-value="1"></i><b>(1)</b>
}</code></pre>
</div>
</div>
<div class="colist arabic">
<table>
<tr>
<td><i class="conum" data-value="1"></i><b>1</b></td>
<td>这个字段是通过 update request 添加的</td>
</tr>
</table>
</div>
<div class="paragraph">
<p>如果不存在，我们会得到一个新的文档：</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-js" data-lang="js">{
    "name" : "Joe Smith",
    "gender": "male"
}</code></pre>
</div>
</div>
</div>
</div>
<div class="sect2">
<h3 id="java-docs-multi-get">5.6. 获取多个文档</h3>
<div class="paragraph">
<p>Multi get API 允许通过 <code>index</code> 和  <code>id</code> 获取多个文档:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java">MultiGetResponse multiGetItemResponses = client.prepareMultiGet()
    .add("twitter", "_doc", "1") <i class="conum" data-value="1"></i><b>(1)</b>
    .add("twitter", "_doc", "2", "3", "4") <i class="conum" data-value="2"></i><b>(2)</b>
    .add("another", "_doc", "foo") <i class="conum" data-value="3"></i><b>(3)</b>
    .get();

for (MultiGetItemResponse itemResponse : multiGetItemResponses) { <i class="conum" data-value="4"></i><b>(4)</b>
    GetResponse response = itemResponse.getResponse();
    if (response.isExists()) { <i class="conum" data-value="5"></i><b>(5)</b>
        String json = response.getSourceAsString(); <i class="conum" data-value="6"></i><b>(6)</b>
    }
}</code></pre>
</div>
</div>
<div class="colist arabic">
<table>
<tr>
<td><i class="conum" data-value="1"></i><b>1</b></td>
<td>通过单独的id获取</td>
</tr>
<tr>
<td><i class="conum" data-value="2"></i><b>2</b></td>
<td>在同一个index中，可以通过多个id获取</td>
</tr>
<tr>
<td><i class="conum" data-value="3"></i><b>3</b></td>
<td>也可以从其它的index中获取文档</td>
</tr>
<tr>
<td><i class="conum" data-value="4"></i><b>4</b></td>
<td>遍历结果集</td>
</tr>
<tr>
<td><i class="conum" data-value="5"></i><b>5</b></td>
<td>查看文档是否存在</td>
</tr>
<tr>
<td><i class="conum" data-value="6"></i><b>6</b></td>
<td>获取 <code>_source</code> 字段</td>
</tr>
</table>
</div>
<div class="paragraph">
<p>有关Multi get操作的更多信息，请查看REST <a href="https://www.elastic.co/guide/en/elasticsearch/reference/6.8/docs-multi-get.html">multi get</a>。</p>
</div>
</div>
<div class="sect2">
<h3 id="java-docs-bulk">5.7. 批处理</h3>
<div class="paragraph">
<p>Bulk API 允许在一次单独的请求中索引或删除多个文档。
下面是一个用法示例:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java">import static org.elasticsearch.common.xcontent.XContentFactory.*;

BulkRequestBuilder bulkRequest = client.prepareBulk();

// either use client#prepare, or use Requests# to directly build index/delete requests
bulkRequest.add(client.prepareIndex("twitter", "_doc", "1")
        .setSource(jsonBuilder()
                    .startObject()
                        .field("user", "kimchy")
                        .field("postDate", new Date())
                        .field("message", "trying out Elasticsearch")
                    .endObject()
                  )
        );

bulkRequest.add(client.prepareIndex("twitter", "_doc", "2")
        .setSource(jsonBuilder()
                    .startObject()
                        .field("user", "kimchy")
                        .field("postDate", new Date())
                        .field("message", "another post")
                    .endObject()
                  )
        );

BulkResponse bulkResponse = bulkRequest.get();
if (bulkResponse.hasFailures()) {
    // process failures by iterating through each bulk response item
}</code></pre>
</div>
</div>
</div>
<div class="sect2">
<h3 id="java-docs-bulk-processor">5.8. 使用批处理工具</h3>
<div class="paragraph">
<p><code>BulkProcessor</code> 类提供了一个简单的 API 来自动执行批处理操作，它可以设置的规则有请求数、请求数据大小、周期。</p>
</div>
<div class="paragraph">
<p>要使用它，首先需要创建一个 <code>BulkProcessor</code> 实例:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java">import org.elasticsearch.action.bulk.BackoffPolicy;
import org.elasticsearch.action.bulk.BulkProcessor;
import org.elasticsearch.common.unit.ByteSizeUnit;
import org.elasticsearch.common.unit.ByteSizeValue;
import org.elasticsearch.common.unit.TimeValue;

BulkProcessor bulkProcessor = BulkProcessor.builder(
        client, <i class="conum" data-value="1"></i><b>(1)</b>
        new BulkProcessor.Listener() {
            @Override
            public void beforeBulk(long executionId,
                                   BulkRequest request) { ... } <i class="conum" data-value="2"></i><b>(2)</b>

            @Override
            public void afterBulk(long executionId,
                                  BulkRequest request,
                                  BulkResponse response) { ... } <i class="conum" data-value="3"></i><b>(3)</b>

            @Override
            public void afterBulk(long executionId,
                                  BulkRequest request,
                                  Throwable failure) { ... } <i class="conum" data-value="4"></i><b>(4)</b>
        })
        .setBulkActions(10000) <i class="conum" data-value="5"></i><b>(5)</b>
        .setBulkSize(new ByteSizeValue(5, ByteSizeUnit.MB)) <i class="conum" data-value="6"></i><b>(6)</b>
        .setFlushInterval(TimeValue.timeValueSeconds(5)) <i class="conum" data-value="7"></i><b>(7)</b>
        .setConcurrentRequests(1) <i class="conum" data-value="8"></i><b>(8)</b>
        .setBackoffPolicy(
            BackoffPolicy.exponentialBackoff(TimeValue.timeValueMillis(100), 3)) <i class="conum" data-value="9"></i><b>(9)</b>
        .build();</code></pre>
</div>
</div>
<div class="colist arabic">
<table>
<tr>
<td><i class="conum" data-value="1"></i><b>1</b></td>
<td>添加Elasticsearch client</td>
</tr>
<tr>
<td><i class="conum" data-value="2"></i><b>2</b></td>
<td>在批处理执行之前被调用。你可以使用 <code>request.numberOfActions()</code> 方法来获取本次批处理的数量</td>
</tr>
<tr>
<td><i class="conum" data-value="3"></i><b>3</b></td>
<td>在批处理执行之后被调用。你可以使用 <code>response.hasFailures()</code> 方法可以查看失败的请求</td>
</tr>
<tr>
<td><i class="conum" data-value="4"></i><b>4</b></td>
<td>在批处理执行失败，或抛出 <code>Throwable</code> 的时候被调用</td>
</tr>
<tr>
<td><i class="conum" data-value="5"></i><b>5</b></td>
<td>设置每次累计达10000个请求就立刻执行批处理</td>
</tr>
<tr>
<td><i class="conum" data-value="6"></i><b>6</b></td>
<td>设置每次数据到达5MB的大小就立刻执行批处理</td>
</tr>
<tr>
<td><i class="conum" data-value="7"></i><b>7</b></td>
<td>设置无论有几条请求，总之每隔5秒就立刻执行批处理</td>
</tr>
<tr>
<td><i class="conum" data-value="8"></i><b>8</b></td>
<td>设置执行批处理请求时允许的最大并发数。0代表每次只执行一个请求，1代表允许1条并发请求</td>
</tr>
<tr>
<td><i class="conum" data-value="9"></i><b>9</b></td>
<td>设置自定义补偿策略:第一次等待100ms，之后每次的间隔时间翻倍，一共重试3次。当批处理执行的时候抛出 <code>EsRejectedExecutionException</code> 异常的时候，会启动重试策略。原因可能是硬件资源太低。如想关闭该策略，可以传入 <code>BackoffPolicy.noBackoff()</code></td>
</tr>
</table>
</div>
<div class="paragraph">
<p>默认情况，<code>BulkProcessor</code> 的配置如下：</p>
</div>
<div class="ulist">
<ul>
<li>
<p><code>1000</code> 个请求</p>
</li>
<li>
<p><code>5mb</code> 大小</p>
</li>
<li>
<p>没有间隔</p>
</li>
<li>
<p>允许1个并发请求</p>
</li>
<li>
<p>第一次等待50ms重试，之后每次的间隔时间翻倍，一共重试8次，总时间大概5.1s左右（这个5.1s是怎么算出来的？麻烦知道的告诉一下）</p>
</li>
</ul>
</div>
<div class="sect3">
<h4 id="java-docs-bulk-processor-requests">5.8.1. 添加请求</h4>
<div class="paragraph">
<p>然后你就可以很简单的向 <code>BulkProcessor</code> 中添加请求了:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java">bulkProcessor.add(new IndexRequest("twitter", "_doc", "1").source(/* your doc here */));
bulkProcessor.add(new DeleteRequest("twitter", "_doc", "2"));</code></pre>
</div>
</div>
</div>
<div class="sect3">
<h4 id="java-docs-bulk-processor-close">5.8.2. 关闭批处理工具</h4>
<div class="paragraph">
<p>当所有文档全部加载到 <code>BulkProcessor</code> 之后，可以使用 <code>awaitClose</code> 或 <code>close</code> 方法关闭它:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java">bulkProcessor.awaitClose(10, TimeUnit.MINUTES);</code></pre>
</div>
</div>
<div class="paragraph">
<p>或</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java">bulkProcessor.close();</code></pre>
</div>
</div>
<div class="paragraph">
<p>如果设置了 <code>flushInterval</code> ，上面两个方法都会刷新剩余的文档并且禁用定时刷新任务。
如果开启了并发请求策略，<code>awaitClose</code> 方法会根据你所指定的时间作出等待，当规定时间内所有批处理请求全部完成时，会返回 <code>true</code> ；
如果在规定时间内，仍有批处理请求未完成，则会返回 <code>false</code> 。
<code>close</code> 方法不会等待批处理请求是否完成，而是直接取消剩余的所有请求。</p>
</div>
</div>
<div class="sect3">
<h4 id="java-docs-bulk-processor-tests">5.8.3. 在测试中使用批处理工具</h4>
<div class="paragraph">
<p>如果你正使用 Elasticsearch 进行测试并且使用的是 <code>BulkProcessor</code> 来批量添加数据，那么最好将并发请求数量设置为 <code>0</code> ，
这样批处理请求将会以同步的方式执行:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java">BulkProcessor bulkProcessor = BulkProcessor.builder(client, new BulkProcessor.Listener() { /* Listener methods */ })
        .setBulkActions(10000)
        .setConcurrentRequests(0)
        .build();

// 添加请求
bulkProcessor.add(/* Your requests */);

// 刷新剩余请求
bulkProcessor.flush();

// 如果你不在需要它了则关闭掉
bulkProcessor.close();

// Refresh your indices
client.admin().indices().prepareRefresh().get();

// 现在可以开始检索啦！
client.prepareSearch().get();</code></pre>
</div>
</div>
</div>
<div class="sect3">
<h4 id="java-docs-bulk-global-parameters">5.8.4. 全局参数</h4>
<div class="paragraph">
<p>全局参数可以在 BulkRequest 和 BulkProcessor 上指定，类似于REST API。
这些全局参数用作默认值，可以被每个子请求的本地参数所覆盖。
有一些参数必须在子请求添加之前被设置， - index, type - ，并且必须在 BulkRequest 或 BulkProcessor 创建期间指定它们。
也有一些是可选的 - pipeline, routing - ，这些可以在批量发送之前的任意时间点指定。</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java">try (BulkProcessor processor = initBulkProcessorBuilder(listener)
        .setGlobalIndex("tweets")
        .setGlobalType("_doc")
        .setGlobalRouting("routing")
        .setGlobalPipeline("pipeline_id")
        .build()) {


    processor.add(new IndexRequest() <i class="conum" data-value="1"></i><b>(1)</b>
        .source(XContentType.JSON, "user", "some user"));
    processor.add(new IndexRequest("blogs", "post_type", "1") <i class="conum" data-value="2"></i><b>(2)</b>
        .source(XContentType.JSON, "title", "some title"));
}</code></pre>
</div>
</div>
<div class="colist arabic">
<table>
<tr>
<td><i class="conum" data-value="1"></i><b>1</b></td>
<td>BulkRequest 的全局参数将应用于子请求</td>
</tr>
<tr>
<td><i class="conum" data-value="2"></i><b>2</b></td>
<td>子请求中的本地管道参数将覆盖BulkRequest中的全局参数</td>
</tr>
</table>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java">BulkRequest request = new BulkRequest();
request.pipeline("globalId");

request.add(new IndexRequest("test", "doc", "1")
    .source(XContentType.JSON, "field", "bulk1")
    .setPipeline("perIndexId")); <i class="conum" data-value="1"></i><b>(1)</b>

request.add(new IndexRequest("test", "doc", "2")
    .source(XContentType.JSON, "field", "bulk2")); <i class="conum" data-value="2"></i><b>(2)</b></code></pre>
</div>
</div>
<div class="colist arabic">
<table>
<tr>
<td><i class="conum" data-value="1"></i><b>1</b></td>
<td>子请求中的本地管道参数将覆盖BulkRequest中的全局参数</td>
</tr>
<tr>
<td><i class="conum" data-value="2"></i><b>2</b></td>
<td>BulkRequest 的全局参数将应用于子请求</td>
</tr>
</table>
</div>
</div>
</div>
<div class="sect2">
<h3 id="java-docs-update-by-query">5.9. 通过条件更新文档</h3>
<div class="paragraph">
<p><code>updateByQuery</code> 最简单的用法是在不更改源的情况下更新同一个index中的所有文档。
这种用法还可以获取新的属性或其它网络映射的改变。</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java">UpdateByQueryRequestBuilder updateByQuery =
  UpdateByQueryAction.INSTANCE.newRequestBuilder(client);
updateByQuery.source("source_index").abortOnVersionConflict(false);
BulkByScrollResponse response = updateByQuery.get();</code></pre>
</div>
</div>
<div class="paragraph">
<p>调用 <code>updateByQuery</code> 方法会优先获取index的快照，然后使用`internal`版本索引所有的文档。</p>
</div>
<div class="admonitionblock note">
<table>
<tr>
<td class="icon">
<i class="fa icon-note" title="Note"></i>
</td>
<td class="content">
当文档正在建立索引时，如果快照版本发生了改变，那么这个文档的版本会发生冲突。
</td>
</tr>
</table>
</div>
<div class="paragraph">
<p>当版本匹配时， <code>updateByQuery</code> 方法会更新文档并增加版本号。</p>
</div>
<div class="paragraph">
<p>所有的修改和查询都失败的时候， <code>updateByQuery</code> 方法就会停止。
这些失败的原因可以从 <code>BulkByScrollResponse#getIndexingFailures</code> 中获得。
但是所有成功的更新操作都会保留并且不会回滚。当第一次发生失败而导致终止时，响应会包含批量请求生成的所有失败消息。</p>
</div>
<div class="paragraph">
<p>为了防止版本冲突而导致 <code>updateByQuery</code> 方法停止，请设置 <code>abortOnVersionConflict(false)</code> 。
第一个例子就是这样做的，因为这个例子是想获取网络映射的修改，并且版本冲突意味着冲突文档在 <code>updateByQuery</code>
的开始和尝试更新修改文档之间更新。这样很好，因为修改操作会获取更新后的网络映射。</p>
</div>
<div class="paragraph">
<p><code>UpdateByQueryRequestBuilder</code> API 支持过滤更新后的文档，并且可以限制更新的数量，还可以通过脚本更新文档:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java">UpdateByQueryRequestBuilder updateByQuery =
  UpdateByQueryAction.INSTANCE.newRequestBuilder(client);
updateByQuery.source("source_index")
    .filter(QueryBuilders.termQuery("level", "awesome"))
    .size(1000)
    .script(new Script(ScriptType.INLINE,
        "ctx._source.awesome = 'absolutely'",
        "painless",
        Collections.emptyMap()));
BulkByScrollResponse response = updateByQuery.get();</code></pre>
</div>
</div>
<div class="paragraph">
<p><code>UpdateByQueryRequestBuilder</code> 还支持直接获取用于查询文档的语句。
你可以用它来改变默认的滚动数量，或者修改匹配文档的请求。</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java">UpdateByQueryRequestBuilder updateByQuery =
  UpdateByQueryAction.INSTANCE.newRequestBuilder(client);
updateByQuery.source("source_index")
    .source()
    .setSize(500);
BulkByScrollResponse response = updateByQuery.get();</code></pre>
</div>
</div>
<div class="paragraph">
<p>您还可以将 <code>size</code> 和排序结合使用，来限制需要更新的文档:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java">UpdateByQueryRequestBuilder updateByQuery =
  UpdateByQueryAction.INSTANCE.newRequestBuilder(client);
updateByQuery.source("source_index")
    .size(100)
    .source()
    .addSort("cat", SortOrder.DESC);
BulkByScrollResponse response = updateByQuery.get();</code></pre>
</div>
</div>
<div class="paragraph">
<p>除了修改文档的 <code>_source</code> 字段之外，您还可以使用脚本来做其它操作，比如 Update API:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java">UpdateByQueryRequestBuilder updateByQuery =
  UpdateByQueryAction.INSTANCE.newRequestBuilder(client);
updateByQuery.source("source_index")
    .script(new Script(
        ScriptType.INLINE,
        "if (ctx._source.awesome == 'absolutely') {"
            + "  ctx.op='noop'"
            + "} else if (ctx._source.awesome == 'lame') {"
            + "  ctx.op='delete'"
            + "} else {"
            + "ctx._source.awesome = 'absolutely'}",
        "painless",
        Collections.emptyMap()));
BulkByScrollResponse response = updateByQuery.get();</code></pre>
</div>
</div>
<div class="paragraph">
<p>与 <a href="#java-docs-update">Update API</a> 一样，您可以通过设置 <code>ctx.op</code> 来改变执行的操作:</p>
</div>
<div class="dlist">
<dl>
<dt class="hdlist1"><code>noop</code></dt>
<dd>
<p>如果这个脚本不会修改任何文档，可以设置 <code>ctx.op = "noop"</code> 。
<code>updateByQuery</code> 操作会从修改中忽略掉这个文档。
这个行为会让响应体中的 <code>noop</code> 计数器增加。</p>
</dd>
<dt class="hdlist1"><code>delete</code></dt>
<dd>
<p>如果这个脚本一定会删除文档，可以设置 <code>ctx.op = "delete"</code> 。 这样在响应体中的 <code>deleted</code> 计数器会有显示。</p>
</dd>
</dl>
</div>
<div class="paragraph">
<p><code>ctx.op</code> 设置其它值会报错。 <code>ctx</code> 设置其它字段也会报错。</p>
</div>
<div class="paragraph">
<p>这个API不允许移动它能接触到的文档，只允许修改source。这是故意这样设计的！我们规定不允许从原始位置将文档移除。</p>
</div>
<div class="paragraph">
<p>你也可以一次在多个索引和类型上执行这些操作，类似于 search API :</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java">UpdateByQueryRequestBuilder updateByQuery =
  UpdateByQueryAction.INSTANCE.newRequestBuilder(client);
updateByQuery.source("foo", "bar").source().setTypes("a", "b");
BulkByScrollResponse response = updateByQuery.get();</code></pre>
</div>
</div>
<div class="paragraph">
<p>如果你提供了 <code>routing</code> 值，则该进程会将路由值复制到滚动查询中，从而将进程限制为匹配该路由值的分片:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java">UpdateByQueryRequestBuilder updateByQuery =
  UpdateByQueryAction.INSTANCE.newRequestBuilder(client);
updateByQuery.source().setRouting("cat");
BulkByScrollResponse response = updateByQuery.get();</code></pre>
</div>
</div>
<div class="paragraph">
<p><code>updateByQuery</code> 也可以通过指定一个像这样的 <code>pipeline</code> 来使用 ingest 节点:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java">UpdateByQueryRequestBuilder updateByQuery =
  UpdateByQueryAction.INSTANCE.newRequestBuilder(client);
updateByQuery.setPipeline("hurray");
BulkByScrollResponse response = updateByQuery.get();</code></pre>
</div>
</div>
<div class="sect3">
<h4 id="java-docs-update-by-query-task-api">5.9.1. 使用任务 API</h4>
<div class="paragraph">
<p>你可以使用 Task API 来获取所有正在运行中的 update-by-query 请求状态:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java">ListTasksResponse tasksList = client.admin().cluster().prepareListTasks()
    .setActions(UpdateByQueryAction.NAME).setDetailed(true).get();
for (TaskInfo info: tasksList.getTasks()) {
    TaskId taskId = info.getTaskId();
    BulkByScrollTask.Status status =
        (BulkByScrollTask.Status) info.getStatus();
    // do stuff
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>使用上面显示的 <code>TaskId</code> 您可以直接地找到task:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java">GetTaskResponse get = client.admin().cluster().prepareGetTask(taskId).get();</code></pre>
</div>
</div>
</div>
<div class="sect3">
<h4 id="java-docs-update-by-query-cancel-task-api">5.9.2. 取消任务 API</h4>
<div class="paragraph">
<p>任何 Update By Query 可以使用 Task Cancel API 来取消:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java">// Cancel all update-by-query requests
client.admin().cluster().prepareCancelTasks()
    .setActions(UpdateByQueryAction.NAME).get().getTasks();
// Cancel a specific update-by-query request
client.admin().cluster().prepareCancelTasks()
    .setTaskId(taskId).get().getTasks();</code></pre>
</div>
</div>
<div class="paragraph">
<p>使用 <code>list tasks</code> API 可以查询 <code>taskId</code> 的值。</p>
</div>
<div class="paragraph">
<p>取消请求通常非常快，但也需要几秒钟。任务状态API会继续列出任务，直到取消完成。</p>
</div>
</div>
<div class="sect3">
<h4 id="java-docs-update-by-query-rethrottle">5.9.3. 二次节流</h4>
<div class="paragraph">
<p>使用 <code>_rethrottle</code> API 可以修改正在运行的 <code>requests_per_second</code> 值:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java">RethrottleAction.INSTANCE.newRequestBuilder(client)
    .setTaskId(taskId)
    .setRequestsPerSecond(2.0f)
    .get();</code></pre>
</div>
</div>
<div class="paragraph">
<p>使用 <code>list tasks</code> API 可以查询 <code>taskId</code> 的值。</p>
</div>
<div class="paragraph">
<p>与 <code>updateByQuery</code> 一样，<code>requests_per_second</code> 可以设置成任何正浮点值来设置throttle的级别，或者使用 <code>Float.POSITIVE_INFINITY</code> 来禁止 throttling。
<code>requests_per_second</code> 值可以加速进程并立刻生效。
为防止滚动超时，要在完成当前批处理后设置 <code>requests_per_second</code> 来减慢进程。</p>
</div>
</div>
</div>
<div class="sect2">
<h3 id="java-docs-reindex">5.10. 重新建立索引</h3>
<div class="paragraph">
<p>查看 <a href="https://www.elastic.co/guide/en/elasticsearch/reference/6.8/docs-reindex.html">reindex API</a>。</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java">BulkByScrollResponse response =
    ReindexAction.INSTANCE.newRequestBuilder(client)
    .source("source_index")
    .destination("target_index")
    .filter(QueryBuilders.matchQuery("category", "xzy")) <i class="conum" data-value="1"></i><b>(1)</b>
    .get();</code></pre>
</div>
</div>
<div class="colist arabic">
<table>
<tr>
<td><i class="conum" data-value="1"></i><b>1</b></td>
<td>可以提供一个查询语句来筛选 source index 到 target index 的文档。</td>
</tr>
</table>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="java-search">6. 查询 API</h2>
<div class="sectionbody">
<div class="paragraph">
<p>Search API 可以执行一个查询操作，返回与查询条件相匹配的结果。
允许跨index查询，也可以跨type查询。
可以使用 <a href="#java-query-dsl">query Java API</a> 作为查询语句。
查询的请求体使用 <code>SearchSourceBuilder</code> 构建。
例:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java">import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.action.search.SearchType;
import org.elasticsearch.index.query.QueryBuilders.*;</code></pre>
</div>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java">SearchResponse response = client.prepareSearch("index1", "index2")
        .setSearchType(SearchType.DFS_QUERY_THEN_FETCH)
        .setQuery(QueryBuilders.termQuery("multi", "test"))                 // Query
        .setPostFilter(QueryBuilders.rangeQuery("age").from(12).to(18))     // Filter
        .setFrom(0).setSize(60).setExplain(true)
        .get();</code></pre>
</div>
</div>
<div class="paragraph">
<p>注意这里所有的参数都不是必填的，下面的例子就是一个最小化的查询请求:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java">// MatchAll on the whole cluster with all default options
SearchResponse response = client.prepareSearch().get();</code></pre>
</div>
</div>
<div class="admonitionblock note">
<table>
<tr>
<td class="icon">
<i class="fa icon-note" title="Note"></i>
</td>
<td class="content">
注意：尽管JavaAPI定义了额外的搜索类型 QUERY_AND_FETCH 和 DFS_QUERY_AND_FETCH ，
但这些模式其实是底层自动优化时使用的模式，不应该由用户通过API指定。
</td>
</tr>
</table>
</div>
<div class="paragraph">
<p>有关索引操作的更多信息，请查看 REST <a href="https://www.elastic.co/guide/en/elasticsearch/reference/6.8/search.html">search</a>。</p>
</div>
<div class="sect2">
<h3 id="java-search-scrolling">6.1. 使用分页</h3>
<div class="paragraph">
<p>首先请阅读 <a href="https://www.elastic.co/guide/en/elasticsearch/reference/6.8/search-request-scroll.html">scroll documentation</a></p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java">import static org.elasticsearch.index.query.QueryBuilders.*;

QueryBuilder qb = termQuery("multi", "test");

SearchResponse scrollResp = client.prepareSearch(test)
        .addSort(FieldSortBuilder.DOC_FIELD_NAME, SortOrder.ASC)
        .setScroll(new TimeValue(60000))
        .setQuery(qb)
        .setSize(100).get(); <i class="conum" data-value="1"></i><b>(1)</b>
do {
    for (SearchHit hit : scrollResp.getHits().getHits()) {
        //Handle the hit...
    }

    scrollResp = client.prepareSearchScroll(scrollResp.getScrollId()).setScroll(new TimeValue(60000)).execute().actionGet();
} while(scrollResp.getHits().getHits().length != 0); <i class="conum" data-value="2"></i><b>(2)</b></code></pre>
</div>
</div>
<div class="colist arabic">
<table>
<tr>
<td><i class="conum" data-value="1"></i><b>1</b></td>
<td>每次查询最多返回100条结果</td>
</tr>
<tr>
<td><i class="conum" data-value="2"></i><b>2</b></td>
<td>没有结果返回的时候就停止循环和游标</td>
</tr>
</table>
</div>
</div>
<div class="sect2">
<h3 id="java-search-msearch">6.2. 多条件查询</h3>
<div class="paragraph">
<p>查看 <a href="https://www.elastic.co/guide/en/elasticsearch/reference/6.8/search-multi-search.html">MultiSearch API Query</a> 文档</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java">SearchRequestBuilder srb1 = client
    .prepareSearch().setQuery(QueryBuilders.queryStringQuery("elasticsearch")).setSize(1);
SearchRequestBuilder srb2 = client
    .prepareSearch().setQuery(QueryBuilders.matchQuery("name", "kimchy")).setSize(1);

MultiSearchResponse sr = client.prepareMultiSearch()
        .add(srb1)
        .add(srb2)
        .get();

long nbHits = 0;
for (MultiSearchResponse.Item item : sr.getResponses()) { <i class="conum" data-value="1"></i><b>(1)</b>
    SearchResponse response = item.getResponse();
    nbHits += response.getHits().getTotalHits();
}</code></pre>
</div>
</div>
<div class="colist arabic">
<table>
<tr>
<td><i class="conum" data-value="1"></i><b>1</b></td>
<td>可以从 MultiSearchResponse#getResponses() 中获取所有独立的响应</td>
</tr>
</table>
</div>
</div>
<div class="sect2">
<h3 id="java-search-aggs">6.3. 使用聚合</h3>
<div class="paragraph">
<p>下面这段代码展示了如何在一次查询中加入两个聚合:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java">SearchResponse sr = client.prepareSearch()
    .setQuery(QueryBuilders.matchAllQuery())
    .addAggregation(
            AggregationBuilders.terms("agg1").field("field")
    )
    .addAggregation(
            AggregationBuilders.dateHistogram("agg2")
                    .field("birth")
                    .dateHistogramInterval(DateHistogramInterval.YEAR)
    )
    .get();

Terms agg1 = sr.getAggregations().get("agg1"); <i class="conum" data-value="1"></i><b>(1)</b>
Histogram agg2 = sr.getAggregations().get("agg2");</code></pre>
</div>
</div>
<div class="colist arabic">
<table>
<tr>
<td><i class="conum" data-value="1"></i><b>1</b></td>
<td>获取某部分结果</td>
</tr>
</table>
</div>
<div class="paragraph">
<p>详情请查看 <a href="#java-aggs">Aggregations Java API</a> 。</p>
</div>
</div>
<div class="sect2">
<h3 id="java-search-terminate-after">6.4. 提前结束查询</h3>
<div class="paragraph">
<p>设置一次查询的最大数，到达这个数量的时候，查询操作就会提前终止。
如果设置了的话，可以在 <code>SearchResponse</code> 对象中使用 <code>isTerminatedEarly()</code> 查看操作是否提前结束。例:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java">SearchResponse sr = client.prepareSearch(INDEX)
    .setTerminateAfter(1000) <i class="conum" data-value="1"></i><b>(1)</b>
    .get();

if (sr.isTerminatedEarly()) {
    // 提前结束时的逻辑
}</code></pre>
</div>
</div>
<div class="colist arabic">
<table>
<tr>
<td><i class="conum" data-value="1"></i><b>1</b></td>
<td>查询到1000个文档就停止</td>
</tr>
</table>
</div>
</div>
<div class="sect2">
<h3 id="java-search-template">6.5. 搜索模板</h3>
<div class="paragraph">
<p>查看 <a href="https://www.elastic.co/guide/en/elasticsearch/reference/6.8/search-template.html">Search Template</a> 文档</p>
</div>
<div class="paragraph">
<p>将模版参数定义成 <code>Map&lt;String,Object&gt;</code> 类型:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java">Map&lt;String, Object&gt; template_params = new HashMap&lt;&gt;();
template_params.put("param_gender", "male");</code></pre>
</div>
</div>
<div class="paragraph">
<p>可以将模版存储在 <code>config/scripts</code> 目录下。
如果你的脚本在 <code>config/scripts/template_gender.mustache</code> ，则可以这样查询：</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-js" data-lang="js">{
    "query" : {
        "match" : {
            "gender" : "{{param_gender}}"
        }
    }
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>创建你的查询请求模版:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java">SearchResponse sr = new SearchTemplateRequestBuilder(client)
    .setScript("template_gender") <i class="conum" data-value="1"></i><b>(1)</b>
    .setScriptType(ScriptService.ScriptType.FILE) <i class="conum" data-value="2"></i><b>(2)</b>
    .setScriptParams(template_params) <i class="conum" data-value="3"></i><b>(3)</b>
    .setRequest(new SearchRequest()) <i class="conum" data-value="4"></i><b>(4)</b>
    .get() <i class="conum" data-value="5"></i><b>(5)</b>
    .getResponse(); <i class="conum" data-value="6"></i><b>(6)</b></code></pre>
</div>
</div>
<div class="colist arabic">
<table>
<tr>
<td><i class="conum" data-value="1"></i><b>1</b></td>
<td>模版名</td>
</tr>
<tr>
<td><i class="conum" data-value="2"></i><b>2</b></td>
<td>模版存储在本地硬盘 <code>gender_template.mustache</code></td>
</tr>
<tr>
<td><i class="conum" data-value="3"></i><b>3</b></td>
<td>模版参数</td>
</tr>
<tr>
<td><i class="conum" data-value="4"></i><b>4</b></td>
<td>设置执行上下文(可以在这里定义index名称)</td>
</tr>
<tr>
<td><i class="conum" data-value="5"></i><b>5</b></td>
<td>执行并获取模版的响应</td>
</tr>
<tr>
<td><i class="conum" data-value="6"></i><b>6</b></td>
<td>从模板响应中获取查询结果</td>
</tr>
</table>
</div>
<div class="paragraph">
<p>你也可以将模版存储在集群state中:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java">client.admin().cluster().preparePutStoredScript()
    .setScriptLang("mustache")
    .setId("template_gender")
    .setSource(new BytesArray(
        "{\n" +
        "    \"query\" : {\n" +
        "        \"match\" : {\n" +
        "            \"gender\" : \"{{param_gender}}\"\n" +
        "        }\n" +
        "    }\n" +
        "}")).get();</code></pre>
</div>
</div>
<div class="paragraph">
<p>要执行该模版，需要使用 <code>ScriptService.ScriptType.STORED</code> 类型:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java">SearchResponse sr = new SearchTemplateRequestBuilder(client)
        .setScript("template_gender") <i class="conum" data-value="1"></i><b>(1)</b>
        .setScriptType(ScriptType.STORED) <i class="conum" data-value="2"></i><b>(2)</b>
        .setScriptParams(template_params) <i class="conum" data-value="3"></i><b>(3)</b>
        .setRequest(new SearchRequest()) <i class="conum" data-value="4"></i><b>(4)</b>
        .get() <i class="conum" data-value="5"></i><b>(5)</b>
        .getResponse(); <i class="conum" data-value="6"></i><b>(6)</b></code></pre>
</div>
</div>
<div class="colist arabic">
<table>
<tr>
<td><i class="conum" data-value="1"></i><b>1</b></td>
<td>模版名</td>
</tr>
<tr>
<td><i class="conum" data-value="2"></i><b>2</b></td>
<td>模版存储在集群state中</td>
</tr>
<tr>
<td><i class="conum" data-value="3"></i><b>3</b></td>
<td>模版参数</td>
</tr>
<tr>
<td><i class="conum" data-value="4"></i><b>4</b></td>
<td>设置执行上下文(可以在这里定义index名称)</td>
</tr>
<tr>
<td><i class="conum" data-value="5"></i><b>5</b></td>
<td>执行并获取模版的响应</td>
</tr>
<tr>
<td><i class="conum" data-value="6"></i><b>6</b></td>
<td>从模板响应中获取查询结果</td>
</tr>
</table>
</div>
<div class="paragraph">
<p>你也可以执行inline(内联)模版:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java">sr = new SearchTemplateRequestBuilder(client)
        .setScript("{\n" + <i class="conum" data-value="1"></i><b>(1)</b>
                "        \"query\" : {\n" +
                "            \"match\" : {\n" +
                "                \"gender\" : \"{{param_gender}}\"\n" +
                "            }\n" +
                "        }\n" +
                "}")
        .setScriptType(ScriptType.INLINE) <i class="conum" data-value="2"></i><b>(2)</b>
        .setScriptParams(template_params) <i class="conum" data-value="3"></i><b>(3)</b>
        .setRequest(new SearchRequest()) <i class="conum" data-value="4"></i><b>(4)</b>
        .get() <i class="conum" data-value="5"></i><b>(5)</b>
        .getResponse(); <i class="conum" data-value="6"></i><b>(6)</b></code></pre>
</div>
</div>
<div class="colist arabic">
<table>
<tr>
<td><i class="conum" data-value="1"></i><b>1</b></td>
<td>模板体</td>
</tr>
<tr>
<td><i class="conum" data-value="2"></i><b>2</b></td>
<td>模版是通过inline方式传递的</td>
</tr>
<tr>
<td><i class="conum" data-value="3"></i><b>3</b></td>
<td>模版参数</td>
</tr>
<tr>
<td><i class="conum" data-value="4"></i><b>4</b></td>
<td>设置执行上下文(可以在这里定义index名称)</td>
</tr>
<tr>
<td><i class="conum" data-value="5"></i><b>5</b></td>
<td>执行并获取模版的响应</td>
</tr>
<tr>
<td><i class="conum" data-value="6"></i><b>6</b></td>
<td>从模板响应中获取查询结果</td>
</tr>
</table>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="java-aggs">7. 聚合</h2>
<div class="sectionbody">
<div class="paragraph">
<p>Elasticsearch 提供了完整的 Java API 来使用aggregation.
请查看 <a href="https://www.elastic.co/guide/en/elasticsearch/reference/6.8/search-aggregations.html">Aggregations guide</a>。</p>
</div>
<div class="paragraph">
<p>使用factory来构建聚合( <code>AggregationBuilders</code> )，并将需要统计的聚合加入到查询语句中:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java">SearchResponse sr = node.client().prepareSearch()
        .setQuery( /* your query */ )
        .addAggregation( /* add an aggregation */ )
        .execute().actionGet();</code></pre>
</div>
</div>
<div class="paragraph">
<p>注意，这里可以添加多个聚合。
详情请查看 <a href="https://www.elastic.co/guide/en/elasticsearch/reference/6.8/search-search.html">Search Java API</a> 。</p>
</div>
<div class="paragraph">
<p>为了构建聚合请求，可以使用内置的 <code>AggregationBuilders</code> 助手。
只需要在你的类中引入:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java">import org.elasticsearch.search.aggregations.AggregationBuilders;</code></pre>
</div>
</div>
<div class="sect2">
<h3 id="agg-build">7.1. 构造聚合</h3>
<div class="paragraph">
<p>如 <a href="https://www.elastic.co/guide/en/elasticsearch/reference/6.8/search-aggregations.html">Aggregations guide</a> 所述，你可以在聚合中定义子聚合。</p>
</div>
<div class="paragraph">
<p>聚合可以是一个 <strong>metrics（指标）</strong> 聚合或者是 <strong>bucket（分组/桶）</strong> 聚合。</p>
</div>
<div class="paragraph">
<p>例如，这里有三个级别的聚合:</p>
</div>
<div class="ulist">
<ul>
<li>
<p>Terms aggregation (bucket)条件聚合(桶)</p>
</li>
<li>
<p>Date Histogram aggregation (bucket)日期柱状图聚合(桶)</p>
</li>
<li>
<p>Average aggregation (metric)平均值聚合(指标)</p>
</li>
</ul>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java">SearchResponse sr = node.client().prepareSearch()
    .addAggregation(
        AggregationBuilders.terms("by_country").field("country")
        .subAggregation(AggregationBuilders.dateHistogram("by_year")
            .field("dateOfBirth")
            .dateHistogramInterval(DateHistogramInterval.YEAR)
            .subAggregation(AggregationBuilders.avg("avg_children").field("children"))
        )
    )
    .execute().actionGet();</code></pre>
</div>
</div>
</div>
<div class="sect2">
<h3 id="agg-metrics">7.2. 指标聚合</h3>
<div class="sect3">
<h4 id="java-aggs-metrics-min">7.2.1. 最小值聚合</h4>
<div class="paragraph">
<p>请查看
<a href="https://www.elastic.co/guide/en/elasticsearch/reference/6.8/search-aggregations-metrics-min-aggregation.html">Min Aggregation</a>
。</p>
</div>
<div class="sect4">
<h5 id="agg-min-pre">准备聚合请求</h5>
<div class="paragraph">
<p>这里有一个创建聚合请求的例子:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java">MinAggregationBuilder aggregation =
        AggregationBuilders
                .min("agg")
                .field("height");</code></pre>
</div>
</div>
</div>
<div class="sect4">
<h5 id="agg-min-res">使用聚合响应</h5>
<div class="paragraph">
<p>导入聚合定义类:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java">import org.elasticsearch.search.aggregations.metrics.min.Min;</code></pre>
</div>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java">// sr is here your SearchResponse object
Min agg = sr.getAggregations().get("agg");
double value = agg.getValue();</code></pre>
</div>
</div>
</div>
</div>
<div class="sect3">
<h4 id="java-aggs-metrics-max">7.2.2. 最大值聚合</h4>
<div class="paragraph">
<p>请查看
<a href="https://www.elastic.co/guide/en/elasticsearch/reference/6.8/search-aggregations-metrics-max-aggregation.html">Max Aggregation</a>
。</p>
</div>
<div class="sect4">
<h5 id="agg-max-pre">准备聚合请求</h5>
<div class="paragraph">
<p>这里有一个创建聚合请求的例子:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java">MaxAggregationBuilder aggregation =
        AggregationBuilders
                .max("agg")
                .field("height");</code></pre>
</div>
</div>
</div>
<div class="sect4">
<h5 id="agg-max-res">使用聚合响应</h5>
<div class="paragraph">
<p>导入聚合定义类:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java">import org.elasticsearch.search.aggregations.metrics.max.Max;</code></pre>
</div>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java">// sr is here your SearchResponse object
Max agg = sr.getAggregations().get("agg");
double value = agg.getValue();</code></pre>
</div>
</div>
</div>
</div>
<div class="sect3">
<h4 id="java-aggs-metrics-sum">7.2.3. 求和聚合</h4>
<div class="paragraph">
<p>请查看
<a href="https://www.elastic.co/guide/en/elasticsearch/reference/6.8/search-aggregations-metrics-sum-aggregation.html">Sum Aggregation</a>
。</p>
</div>
<div class="sect4">
<h5 id="agg-sum-pre">准备聚合请求</h5>
<div class="paragraph">
<p>这里有一个创建聚合请求的例子:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java">SumAggregationBuilder aggregation =
        AggregationBuilders
                .sum("agg")
                .field("height");</code></pre>
</div>
</div>
</div>
<div class="sect4">
<h5 id="agg-sum-res">使用聚合响应</h5>
<div class="paragraph">
<p>导入聚合定义类:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java">import org.elasticsearch.search.aggregations.metrics.sum.Sum;</code></pre>
</div>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java">// sr is here your SearchResponse object
Sum agg = sr.getAggregations().get("agg");
double value = agg.getValue();</code></pre>
</div>
</div>
</div>
</div>
<div class="sect3">
<h4 id="java-aggs-metrics-avg">7.2.4. 平均值聚合</h4>
<div class="paragraph">
<p>请查看
<a href="https://www.elastic.co/guide/en/elasticsearch/reference/6.8/search-aggregations-metrics-avg-aggregation.html">Avg Aggregation</a>
。</p>
</div>
<div class="sect4">
<h5 id="agg-avg-pre">准备聚合请求</h5>
<div class="paragraph">
<p>这里有一个创建聚合请求的例子:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java">AvgAggregationBuilder aggregation =
        AggregationBuilders
                .avg("agg")
                .field("height");</code></pre>
</div>
</div>
</div>
<div class="sect4">
<h5 id="agg-avg-res">使用聚合响应</h5>
<div class="paragraph">
<p>导入聚合定义类:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java">import org.elasticsearch.search.aggregations.metrics.avg.Avg;</code></pre>
</div>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java">// sr is here your SearchResponse object
Avg agg = sr.getAggregations().get("agg");
double value = agg.getValue();</code></pre>
</div>
</div>
</div>
</div>
<div class="sect3">
<h4 id="java-aggs-metrics-stats">7.2.5. 统计聚合</h4>
<div class="paragraph">
<p>请查看
<a href="https://www.elastic.co/guide/en/elasticsearch/reference/6.8/search-aggregations-metrics-stats-aggregation.html">Stats Aggregation</a>
。</p>
</div>
<div class="sect4">
<h5 id="agg-stats-pre">准备聚合请求</h5>
<div class="paragraph">
<p>这里有一个创建聚合请求的例子:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java">StatsAggregationBuilder aggregation =
        AggregationBuilders
                .stats("agg")
                .field("height");</code></pre>
</div>
</div>
</div>
<div class="sect4">
<h5 id="agg-stats-res">使用聚合响应</h5>
<div class="paragraph">
<p>导入聚合定义类:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java">import org.elasticsearch.search.aggregations.metrics.stats.Stats;</code></pre>
</div>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java">// sr is here your SearchResponse object
Stats agg = sr.getAggregations().get("agg");
double min = agg.getMin();
double max = agg.getMax();
double avg = agg.getAvg();
double sum = agg.getSum();
long count = agg.getCount();</code></pre>
</div>
</div>
</div>
</div>
<div class="sect3">
<h4 id="java-aggs-metrics-extendedstats">7.2.6. 统计聚合拓展</h4>
<div class="paragraph">
<p>请查看
<a href="https://www.elastic.co/guide/en/elasticsearch/reference/6.8/search-aggregations-metrics-extendedstats-aggregation.html">Extended Stats Aggregation</a>
。</p>
</div>
<div class="sect4">
<h5 id="agg-stats-ext-pre">准备聚合请求</h5>
<div class="paragraph">
<p>这里有一个创建聚合请求的例子:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java">ExtendedStatsAggregationBuilder aggregation =
        AggregationBuilders
                .extendedStats("agg")
                .field("height");</code></pre>
</div>
</div>
</div>
<div class="sect4">
<h5 id="agg-stats-ext-res">使用聚合响应</h5>
<div class="paragraph">
<p>导入聚合定义类:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java">import org.elasticsearch.search.aggregations.metrics.stats.extended.ExtendedStats;</code></pre>
</div>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java">// sr is here your SearchResponse object
ExtendedStats agg = sr.getAggregations().get("agg");
double min = agg.getMin();
double max = agg.getMax();
double avg = agg.getAvg();
double sum = agg.getSum();
long count = agg.getCount();
double stdDeviation = agg.getStdDeviation();
double sumOfSquares = agg.getSumOfSquares();
double variance = agg.getVariance();</code></pre>
</div>
</div>
</div>
</div>
<div class="sect3">
<h4 id="java-aggs-metrics-valuecount">7.2.7. 数量聚合</h4>
<div class="paragraph">
<p>请查看
<a href="https://www.elastic.co/guide/en/elasticsearch/reference/6.8/search-aggregations-metrics-valuecount-aggregation.html">Value Count Aggregation</a>
。</p>
</div>
<div class="sect4">
<h5 id="agg-valuecount-pre">准备聚合请求</h5>
<div class="paragraph">
<p>这里有一个创建聚合请求的例子:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java">ValueCountAggregationBuilder aggregation =
        AggregationBuilders
                .count("agg")
                .field("height");</code></pre>
</div>
</div>
</div>
<div class="sect4">
<h5 id="agg-valuecount-res">使用聚合响应</h5>
<div class="paragraph">
<p>导入聚合定义类:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java">import org.elasticsearch.search.aggregations.metrics.valuecount.ValueCount;</code></pre>
</div>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java">// sr is here your SearchResponse object
ValueCount agg = sr.getAggregations().get("agg");
long value = agg.getValue();</code></pre>
</div>
</div>
</div>
</div>
<div class="sect3">
<h4 id="java-aggs-metrics-percentile">7.2.8. 百分比聚合</h4>
<div class="paragraph">
<p>请查看
<a href="https://www.elastic.co/guide/en/elasticsearch/reference/6.8/search-aggregations-metrics-percentile-aggregation.html">Percentile Aggregation</a>
。</p>
</div>
<div class="sect4">
<h5 id="agg-percentile-pre">准备聚合请求</h5>
<div class="paragraph">
<p>这里有一个创建聚合请求的例子:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java">PercentilesAggregationBuilder aggregation =
        AggregationBuilders
                .percentiles("agg")
                .field("height");</code></pre>
</div>
</div>
<div class="paragraph">
<p>当然你可以提供自己的数字，而不是使用默认值:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java">PercentilesAggregationBuilder aggregation =
        AggregationBuilders
                .percentiles("agg")
                .field("height")
                .percentiles(1.0, 5.0, 10.0, 20.0, 30.0, 75.0, 95.0, 99.0);</code></pre>
</div>
</div>
</div>
<div class="sect4">
<h5 id="agg-percentile-res">使用聚合响应</h5>
<div class="paragraph">
<p>导入聚合定义类:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java">import org.elasticsearch.search.aggregations.metrics.percentiles.Percentile;
import org.elasticsearch.search.aggregations.metrics.percentiles.Percentiles;</code></pre>
</div>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java">// sr is here your SearchResponse object
Percentiles agg = sr.getAggregations().get("agg");
// For each entry
for (Percentile entry : agg) {
    double percent = entry.getPercent();    // Percent
    double value = entry.getValue();        // Value

    logger.info("percent [{}], value [{}]", percent, value);
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>上面的例子一般会返回这样的结果:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-text" data-lang="text">percent [1.0], value [0.814338896154595]
percent [5.0], value [0.8761912455821302]
percent [25.0], value [1.173346540141847]
percent [50.0], value [1.5432023318692198]
percent [75.0], value [1.923915462033674]
percent [95.0], value [2.2273644908535335]
percent [99.0], value [2.284989339108279]</code></pre>
</div>
</div>
</div>
</div>
<div class="sect3">
<h4 id="java-aggs-metrics-percentile-rank">7.2.9. 百分比排名聚合</h4>
<div class="paragraph">
<p>请查看
<a href="https://www.elastic.co/guide/en/elasticsearch/reference/6.8/search-aggregations-metrics-percentile-rank-aggregation.html">Percentile Ranks Aggregation</a>
。</p>
</div>
<div class="sect4">
<h5 id="agg-percentile-rank-pre">准备聚合请求</h5>
<div class="paragraph">
<p>这里有一个创建聚合请求的例子:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java">PercentileRanksAggregationBuilder aggregation =
        AggregationBuilders
                .percentileRanks("agg")
                .field("height")
                .values(1.24, 1.91, 2.22);</code></pre>
</div>
</div>
</div>
<div class="sect4">
<h5 id="agg-percentile-rank-res">使用聚合响应</h5>
<div class="paragraph">
<p>导入聚合定义类:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java">import org.elasticsearch.search.aggregations.metrics.percentiles.Percentile;
import org.elasticsearch.search.aggregations.metrics.percentiles.PercentileRanks;</code></pre>
</div>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java">// sr is here your SearchResponse object
PercentileRanks agg = sr.getAggregations().get("agg");
// For each entry
for (Percentile entry : agg) {
    double percent = entry.getPercent();    // Percent
    double value = entry.getValue();        // Value

    logger.info("percent [{}], value [{}]", percent, value);
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>一般会返回如下结果:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-text" data-lang="text">percent [29.664353095090945], value [1.24]
percent [73.9335313461868], value [1.91]
percent [94.40095147327283], value [2.22]</code></pre>
</div>
</div>
</div>
</div>
<div class="sect3">
<h4 id="java-aggs-metrics-cardinality">7.2.10. 基数聚合</h4>
<div class="paragraph">
<p>请查看
<a href="https://www.elastic.co/guide/en/elasticsearch/reference/6.8/search-aggregations-metrics-cardinality-aggregation.html">Cardinality Aggregation</a>
。</p>
</div>
<div class="sect4">
<h5 id="agg-cardinality-pre">准备聚合请求</h5>
<div class="paragraph">
<p>这里有一个创建聚合请求的例子:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java">CardinalityAggregationBuilder aggregation =
        AggregationBuilders
                .cardinality("agg")
                .field("tags");</code></pre>
</div>
</div>
</div>
<div class="sect4">
<h5 id="agg-cardinality-res">使用聚合响应</h5>
<div class="paragraph">
<p>导入聚合定义类:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java">import org.elasticsearch.search.aggregations.metrics.cardinality.Cardinality;</code></pre>
</div>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java">// sr is here your SearchResponse object
Cardinality agg = sr.getAggregations().get("agg");
long value = agg.getValue();</code></pre>
</div>
</div>
</div>
</div>
<div class="sect3">
<h4 id="java-aggs-metrics-geobounds">7.2.11. 地理范围聚合</h4>
<div class="paragraph">
<p>请查看
<a href="https://www.elastic.co/guide/en/elasticsearch/reference/6.8/search-aggregations-metrics-geobounds-aggregation.html">Geo Bounds Aggregation</a>
。</p>
</div>
<div class="sect4">
<h5 id="agg-geobounds-pre">准备聚合请求</h5>
<div class="paragraph">
<p>这里有一个创建聚合请求的例子:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java">GeoBoundsBuilder aggregation =
        GeoBoundsAggregationBuilder
                .geoBounds("agg")
                .field("address.location")
                .wrapLongitude(true);</code></pre>
</div>
</div>
</div>
<div class="sect4">
<h5 id="agg-geobounds-res">使用聚合响应</h5>
<div class="paragraph">
<p>导入聚合定义类:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java">import org.elasticsearch.search.aggregations.metrics.geobounds.GeoBounds;</code></pre>
</div>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java">// sr is here your SearchResponse object
GeoBounds agg = sr.getAggregations().get("agg");
GeoPoint bottomRight = agg.bottomRight();
GeoPoint topLeft = agg.topLeft();
logger.info("bottomRight {}, topLeft {}", bottomRight, topLeft);</code></pre>
</div>
</div>
<div class="paragraph">
<p>一般会返回如下结果:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-text" data-lang="text">bottomRight [40.70500764381921, 13.952946866893775], topLeft [53.49603022435221, -4.190029308156676]</code></pre>
</div>
</div>
</div>
</div>
<div class="sect3">
<h4 id="java-aggs-metrics-tophits">7.2.12. 热门聚合</h4>
<div class="paragraph">
<p>请查看
<a href="https://www.elastic.co/guide/en/elasticsearch/reference/6.8/search-aggregations-metrics-top-hits-aggregation.html">Top Hits Aggregation</a>
。</p>
</div>
<div class="sect4">
<h5 id="agg-tophits-pre">准备聚合请求</h5>
<div class="paragraph">
<p>这里有一个创建聚合请求的例子:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java">AggregationBuilder aggregation =
    AggregationBuilders
        .terms("agg").field("gender")
        .subAggregation(
            AggregationBuilders.topHits("top")
        );</code></pre>
</div>
</div>
<div class="paragraph">
<p>大多数在查询时使用的参数在这里都可以使用，比如 <code>from</code>, <code>size</code>, <code>sort</code>, <code>highlight</code>, <code>explain</code>&#8230;&#8203;</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java">AggregationBuilder aggregation =
    AggregationBuilders
        .terms("agg").field("gender")
        .subAggregation(
            AggregationBuilders.topHits("top")
                .explain(true)
                .size(1)
                .from(10)
        );</code></pre>
</div>
</div>
</div>
<div class="sect4">
<h5 id="agg-tophits-res">使用聚合响应</h5>
<div class="paragraph">
<p>导入聚合定义类:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java">import org.elasticsearch.search.aggregations.bucket.terms.Terms;
import org.elasticsearch.search.aggregations.metrics.tophits.TopHits;</code></pre>
</div>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java">// sr is here your SearchResponse object
Terms agg = sr.getAggregations().get("agg");

// For each entry
for (Terms.Bucket entry : agg.getBuckets()) {
    String key = entry.getKey();                    // bucket key
    long docCount = entry.getDocCount();            // Doc count
    logger.info("key [{}], doc_count [{}]", key, docCount);

    // We ask for top_hits for each bucket
    TopHits topHits = entry.getAggregations().get("top");
    for (SearchHit hit : topHits.getHits().getHits()) {
        logger.info(" -&gt; id [{}], _source [{}]", hit.getId(), hit.getSourceAsString());
    }
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>一般会返回如下结果:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-text" data-lang="text">key [male], doc_count [5107]
 -&gt; id [AUnzSZze9k7PKXtq04x2], _source [{"gender":"male",...}]
 -&gt; id [AUnzSZzj9k7PKXtq04x4], _source [{"gender":"male",...}]
 -&gt; id [AUnzSZzl9k7PKXtq04x5], _source [{"gender":"male",...}]
key [female], doc_count [4893]
 -&gt; id [AUnzSZzM9k7PKXtq04xy], _source [{"gender":"female",...}]
 -&gt; id [AUnzSZzp9k7PKXtq04x8], _source [{"gender":"female",...}]
 -&gt; id [AUnzSZ0W9k7PKXtq04yS], _source [{"gender":"female",...}]</code></pre>
</div>
</div>
</div>
</div>
<div class="sect3">
<h4 id="java-aggs-metrics-scripted-metric">7.2.13. 脚本指标聚合</h4>
<div class="paragraph">
<p>请查看
<a href="https://www.elastic.co/guide/en/elasticsearch/reference/6.8/search-aggregations-metrics-scripted-metric-aggregation.html">Scripted Metric Aggregation</a>
。</p>
</div>
<div class="sect4">
<h5 id="agg-scripted-pre">准备聚合请求</h5>
<div class="paragraph">
<p>这里有一个创建聚合请求的例子:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java">ScriptedMetricAggregationBuilder aggregation = AggregationBuilders
    .scriptedMetric("agg")
    .initScript(new Script("state.heights = []"))
    .mapScript(new Script("state.heights.add(doc.gender.value == 'male' ? doc.height.value : -1.0 * doc.height.value)"));</code></pre>
</div>
</div>
<div class="paragraph">
<p>你也还可以指定将在每个shard上执行的 <code>combine</code> 脚本:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java">ScriptedMetricAggregationBuilder aggregation = AggregationBuilders
    .scriptedMetric("agg")
    .initScript(new Script("state.heights = []"))
    .mapScript(new Script("state.heights.add(doc.gender.value == 'male' ? doc.height.value : -1.0 * doc.height.value)"))
    .combineScript(new Script("double heights_sum = 0.0; for (t in state.heights) { heights_sum += t } return heights_sum"));</code></pre>
</div>
</div>
<div class="paragraph">
<p>您还可以指定将在每个接收请求的节点上执行的 <code>reduce</code> 脚本:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java">ScriptedMetricAggregationBuilder aggregation = AggregationBuilders
    .scriptedMetric("agg")
    .initScript(new Script("state.heights = []"))
    .mapScript(new Script("state.heights.add(doc.gender.value == 'male' ? doc.height.value : -1.0 * doc.height.value)"))
    .combineScript(new Script("double heights_sum = 0.0; for (t in state.heights) { heights_sum += t } return heights_sum"))
    .reduceScript(new Script("double heights_sum = 0.0; for (a in states) { heights_sum += a } return heights_sum"));</code></pre>
</div>
</div>
</div>
<div class="sect4">
<h5 id="agg-scripted-res">使用聚合响应</h5>
<div class="paragraph">
<p>导入聚合定义类:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java">import org.elasticsearch.search.aggregations.bucket.terms.Terms;
import org.elasticsearch.search.aggregations.metrics.tophits.TopHits;</code></pre>
</div>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java">// sr is here your SearchResponse object
ScriptedMetric agg = sr.getAggregations().get("agg");
Object scriptedResult = agg.aggregation();
logger.info("scriptedResult [{}]", scriptedResult);</code></pre>
</div>
</div>
<div class="paragraph">
<p>请注意，聚合的结果取决于你所构建的脚本。
第一个例子一般会返回如下结果:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-text" data-lang="text">scriptedResult object [ArrayList]
scriptedResult [ {
"heights" : [ 1.122218480146643, -1.8148918111233887, -1.7626731575142909, ... ]
}, {
"heights" : [ -0.8046067304119863, -2.0785486707864553, -1.9183567430207953, ... ]
}, {
"heights" : [ 2.092635728868694, 1.5697545960886536, 1.8826954461968808, ... ]
}, {
"heights" : [ -2.1863201099468403, 1.6328549117346856, -1.7078288405893842, ... ]
}, {
"heights" : [ 1.6043904836424177, -2.0736538674414025, 0.9898266674373053, ... ]
} ]</code></pre>
</div>
</div>
<div class="paragraph">
<p>第二个例子会返回:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-text" data-lang="text">scriptedResult object [ArrayList]
scriptedResult [-41.279615707402876,
                -60.88007362339038,
                38.823270659734256,
                14.840192739445632,
                11.300902755741326]</code></pre>
</div>
</div>
<div class="paragraph">
<p>最后一个例子会返回:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-text" data-lang="text">scriptedResult object [Double]
scriptedResult [2.171917696507009]</code></pre>
</div>
</div>
</div>
</div>
</div>
<div class="sect2">
<h3 id="agg-bucket">7.3. 分组聚合</h3>
<div class="sect3">
<h4 id="java-aggs-bucket-global">7.3.1. Global Aggregation</h4>
<div class="paragraph">
<p>请查看
<a href="https://www.elastic.co/guide/en/elasticsearch/reference/6.8/search-aggregations-bucket-global-aggregation.html">Global Aggregation</a>
。</p>
</div>
<div class="sect4">
<h5 id="_prepare_aggregation_request">Prepare aggregation request</h5>
<div class="paragraph">
<p>这里有一个创建聚合请求的例子:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java">AggregationBuilders
    .global("agg")
    .subAggregation(AggregationBuilders.terms("genders").field("gender"));</code></pre>
</div>
</div>
</div>
<div class="sect4">
<h5 id="_use_aggregation_response">Use aggregation response</h5>
<div class="paragraph">
<p>导入聚合定义类:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java">import org.elasticsearch.search.aggregations.bucket.global.Global;</code></pre>
</div>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java">// sr is here your SearchResponse object
Global agg = sr.getAggregations().get("agg");
agg.getDocCount(); // Doc count</code></pre>
</div>
</div>
</div>
</div>
<div class="sect3">
<h4 id="java-aggs-bucket-filter">7.3.2. Filter Aggregation</h4>
<div class="paragraph">
<p>请查看
<a href="https://www.elastic.co/guide/en/elasticsearch/reference/6.8/search-aggregations-bucket-filter-aggregation.html">Filter Aggregation</a>
。</p>
</div>
<div class="sect4">
<h5 id="_prepare_aggregation_request_2">Prepare aggregation request</h5>
<div class="paragraph">
<p>这里有一个创建聚合请求的例子:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java">AggregationBuilders
    .filter("agg", QueryBuilders.termQuery("gender", "male"));</code></pre>
</div>
</div>
</div>
<div class="sect4">
<h5 id="_use_aggregation_response_2">Use aggregation response</h5>
<div class="paragraph">
<p>导入聚合定义类:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java">import org.elasticsearch.search.aggregations.bucket.filter.Filter;</code></pre>
</div>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java">// sr is here your SearchResponse object
Filter agg = sr.getAggregations().get("agg");
agg.getDocCount(); // Doc count</code></pre>
</div>
</div>
</div>
</div>
<div class="sect3">
<h4 id="java-aggs-bucket-filters">7.3.3. Filters Aggregation</h4>
<div class="paragraph">
<p>请查看
<a href="https://www.elastic.co/guide/en/elasticsearch/reference/6.8/search-aggregations-bucket-filters-aggregation.html">Filters Aggregation</a>
。</p>
</div>
<div class="sect4">
<h5 id="_prepare_aggregation_request_3">Prepare aggregation request</h5>
<div class="paragraph">
<p>这里有一个创建聚合请求的例子:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java">AggregationBuilder aggregation =
    AggregationBuilders
        .filters("agg",
            new FiltersAggregator.KeyedFilter("men", QueryBuilders.termQuery("gender", "male")),
            new FiltersAggregator.KeyedFilter("women", QueryBuilders.termQuery("gender", "female")));</code></pre>
</div>
</div>
</div>
<div class="sect4">
<h5 id="_use_aggregation_response_3">Use aggregation response</h5>
<div class="paragraph">
<p>导入聚合定义类:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java">import org.elasticsearch.search.aggregations.bucket.filters.Filters;</code></pre>
</div>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java">// sr is here your SearchResponse object
Filters agg = sr.getAggregations().get("agg");

// For each entry
for (Filters.Bucket entry : agg.getBuckets()) {
    String key = entry.getKeyAsString();            // bucket key
    long docCount = entry.getDocCount();            // Doc count
    logger.info("key [{}], doc_count [{}]", key, docCount);
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>一般会返回如下结果:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-text" data-lang="text">key [men], doc_count [4982]
key [women], doc_count [5018]</code></pre>
</div>
</div>
</div>
</div>
<div class="sect3">
<h4 id="java-aggs-bucket-missing">7.3.4. Missing Aggregation</h4>
<div class="paragraph">
<p>请查看
<a href="https://www.elastic.co/guide/en/elasticsearch/reference/6.8/search-aggregations-bucket-missing-aggregation.html">Missing Aggregation</a>
。</p>
</div>
<div class="sect4">
<h5 id="_prepare_aggregation_request_4">Prepare aggregation request</h5>
<div class="paragraph">
<p>这里有一个创建聚合请求的例子:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java">AggregationBuilders.missing("agg").field("gender");</code></pre>
</div>
</div>
</div>
<div class="sect4">
<h5 id="_use_aggregation_response_4">Use aggregation response</h5>
<div class="paragraph">
<p>导入聚合定义类:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java">import org.elasticsearch.search.aggregations.bucket.missing.Missing;</code></pre>
</div>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java">// sr is here your SearchResponse object
Missing agg = sr.getAggregations().get("agg");
agg.getDocCount(); // Doc count</code></pre>
</div>
</div>
</div>
</div>
<div class="sect3">
<h4 id="java-aggs-bucket-nested">7.3.5. Nested Aggregation</h4>
<div class="paragraph">
<p>请查看
<a href="https://www.elastic.co/guide/en/elasticsearch/reference/6.8/search-aggregations-bucket-nested-aggregation.html">Nested Aggregation</a>
。</p>
</div>
<div class="sect4">
<h5 id="_prepare_aggregation_request_5">Prepare aggregation request</h5>
<div class="paragraph">
<p>这里有一个创建聚合请求的例子:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java">AggregationBuilders
    .nested("agg", "resellers");</code></pre>
</div>
</div>
</div>
<div class="sect4">
<h5 id="_use_aggregation_response_5">Use aggregation response</h5>
<div class="paragraph">
<p>导入聚合定义类:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java">import org.elasticsearch.search.aggregations.bucket.nested.Nested;</code></pre>
</div>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java">// sr is here your SearchResponse object
Nested agg = sr.getAggregations().get("agg");
agg.getDocCount(); // Doc count</code></pre>
</div>
</div>
</div>
</div>
<div class="sect3">
<h4 id="java-aggs-bucket-reverse-nested">7.3.6. Reverse Nested Aggregation</h4>
<div class="paragraph">
<p>请查看
<a href="https://www.elastic.co/guide/en/elasticsearch/reference/6.8/search-aggregations-bucket-reverse-nested-aggregation.html">Reverse Nested Aggregation</a>
。</p>
</div>
<div class="sect4">
<h5 id="_prepare_aggregation_request_6">Prepare aggregation request</h5>
<div class="paragraph">
<p>这里有一个创建聚合请求的例子:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java">AggregationBuilder aggregation =
    AggregationBuilders
        .nested("agg", "resellers")
        .subAggregation(
                AggregationBuilders
                        .terms("name").field("resellers.name")
                        .subAggregation(
                                AggregationBuilders
                                        .reverseNested("reseller_to_product")
                        )
        );</code></pre>
</div>
</div>
</div>
<div class="sect4">
<h5 id="_use_aggregation_response_6">Use aggregation response</h5>
<div class="paragraph">
<p>导入聚合定义类:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java">import org.elasticsearch.search.aggregations.bucket.nested.Nested;
import org.elasticsearch.search.aggregations.bucket.nested.ReverseNested;
import org.elasticsearch.search.aggregations.bucket.terms.Terms;</code></pre>
</div>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java">// sr is here your SearchResponse object
Nested agg = sr.getAggregations().get("agg");
Terms name = agg.getAggregations().get("name");
for (Terms.Bucket bucket : name.getBuckets()) {
    ReverseNested resellerToProduct = bucket.getAggregations().get("reseller_to_product");
    resellerToProduct.getDocCount(); // Doc count
}</code></pre>
</div>
</div>
</div>
</div>
<div class="sect3">
<h4 id="java-aggs-bucket-children">7.3.7. Children Aggregation</h4>
<div class="paragraph">
<p>请查看
<a href="https://www.elastic.co/guide/en/elasticsearch/reference/6.8/search-aggregations-bucket-children-aggregation.html">Children Aggregation</a>
。</p>
</div>
<div class="sect4">
<h5 id="_prepare_aggregation_request_7">Prepare aggregation request</h5>
<div class="paragraph">
<p>这里有一个创建聚合请求的例子:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java">AggregationBuilder aggregation =
    AggregationBuilders
        .children("agg", "reseller"); <i class="conum" data-value="1"></i><b>(1)</b></code></pre>
</div>
</div>
<div class="colist arabic">
<table>
<tr>
<td><i class="conum" data-value="1"></i><b>1</b></td>
<td><code>"agg"</code> 是聚合的名字，  <code>"reseller"</code> 是子类型</td>
</tr>
</table>
</div>
</div>
<div class="sect4">
<h5 id="_use_aggregation_response_7">Use aggregation response</h5>
<div class="paragraph">
<p>导入聚合定义类:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java">import org.elasticsearch.join.aggregations.Children;</code></pre>
</div>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java">// sr is here your SearchResponse object
Children agg = sr.getAggregations().get("agg");
agg.getDocCount(); // Doc count</code></pre>
</div>
</div>
</div>
</div>
<div class="sect3">
<h4 id="java-aggs-bucket-terms">7.3.8. Terms Aggregation</h4>
<div class="paragraph">
<p>请查看
<a href="https://www.elastic.co/guide/en/elasticsearch/reference/6.8/search-aggregations-bucket-terms-aggregation.html">Terms Aggregation</a>
。</p>
</div>
<div class="sect4">
<h5 id="_prepare_aggregation_request_8">Prepare aggregation request</h5>
<div class="paragraph">
<p>这里有一个创建聚合请求的例子:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java">AggregationBuilders
    .terms("genders")
    .field("gender");</code></pre>
</div>
</div>
</div>
<div class="sect4">
<h5 id="_use_aggregation_response_8">Use aggregation response</h5>
<div class="paragraph">
<p>导入聚合定义类:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java">import org.elasticsearch.search.aggregations.bucket.terms.Terms;</code></pre>
</div>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java">// sr is here your SearchResponse object
Terms genders = sr.getAggregations().get("genders");

// For each entry
for (Terms.Bucket entry : genders.getBuckets()) {
    entry.getKey();      // Term
    entry.getDocCount(); // Doc count
}</code></pre>
</div>
</div>
</div>
<div class="sect4">
<h5 id="_order">Order</h5>
<div class="paragraph">
<p>导入BucketOrder类:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java">import org.elasticsearch.search.aggregations.BucketOrder;</code></pre>
</div>
</div>
<div class="paragraph">
<p>按 <code>doc_count</code> 升序方式进行排序:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java">AggregationBuilders
    .terms("genders")
    .field("gender")
    .order(BucketOrder.count(true))</code></pre>
</div>
</div>
<div class="paragraph">
<p>Ordering the buckets alphabetically by their terms in an ascending manner:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java">AggregationBuilders
    .terms("genders")
    .field("gender")
    .order(BucketOrder.key(true))</code></pre>
</div>
</div>
<div class="paragraph">
<p>Ordering the buckets by single value metrics sub-aggregation (identified by the aggregation name):</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java">AggregationBuilders
    .terms("genders")
    .field("gender")
    .order(BucketOrder.aggregation("avg_height", false))
    .subAggregation(
        AggregationBuilders.avg("avg_height").field("height")
    )</code></pre>
</div>
</div>
<div class="paragraph">
<p>按多个条件排序:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java">AggregationBuilders
    .terms("genders")
    .field("gender")
    .order(BucketOrder.compound( // in order of priority:
        BucketOrder.aggregation("avg_height", false), // sort by sub-aggregation first
        BucketOrder.count(true))) // then bucket count as a tie-breaker
    .subAggregation(
        AggregationBuilders.avg("avg_height").field("height")
    )</code></pre>
</div>
</div>
</div>
</div>
<div class="sect3">
<h4 id="java-aggs-bucket-significantterms">7.3.9. Significant Terms Aggregation</h4>
<div class="paragraph">
<p>请查看
<a href="https://www.elastic.co/guide/en/elasticsearch/reference/6.8/search-aggregations-bucket-significantterms-aggregation.html">Significant Terms Aggregation</a>
。</p>
</div>
<div class="sect4">
<h5 id="_prepare_aggregation_request_9">Prepare aggregation request</h5>
<div class="paragraph">
<p>这里有一个创建聚合请求的例子:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java">AggregationBuilder aggregation =
        AggregationBuilders
                .significantTerms("significant_countries")
                .field("address.country");

// Let say you search for men only
SearchResponse sr = client.prepareSearch()
        .setQuery(QueryBuilders.termQuery("gender", "male"))
        .addAggregation(aggregation)
        .get();</code></pre>
</div>
</div>
</div>
<div class="sect4">
<h5 id="_use_aggregation_response_9">Use aggregation response</h5>
<div class="paragraph">
<p>导入聚合定义类:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java">import org.elasticsearch.search.aggregations.bucket.significant.SignificantTerms;</code></pre>
</div>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java">// sr is here your SearchResponse object
SignificantTerms agg = sr.getAggregations().get("significant_countries");

// For each entry
for (SignificantTerms.Bucket entry : agg.getBuckets()) {
    entry.getKey();      // Term
    entry.getDocCount(); // Doc count
}</code></pre>
</div>
</div>
</div>
</div>
<div class="sect3">
<h4 id="java-aggs-bucket-range">7.3.10. Range Aggregation</h4>
<div class="paragraph">
<p>请查看
<a href="https://www.elastic.co/guide/en/elasticsearch/reference/6.8/search-aggregations-bucket-range-aggregation.html">Range Aggregation</a>
。</p>
</div>
<div class="sect4">
<h5 id="_prepare_aggregation_request_10">Prepare aggregation request</h5>
<div class="paragraph">
<p>这里有一个创建聚合请求的例子:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java">AggregationBuilder aggregation =
        AggregationBuilders
                .range("agg")
                .field("height")
                .addUnboundedTo(1.0f)               // from -infinity to 1.0 (excluded)
                .addRange(1.0f, 1.5f)               // from 1.0 to 1.5 (excluded)
                .addUnboundedFrom(1.5f);            // from 1.5 to +infinity</code></pre>
</div>
</div>
</div>
<div class="sect4">
<h5 id="_use_aggregation_response_10">Use aggregation response</h5>
<div class="paragraph">
<p>导入聚合定义类:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java">import org.elasticsearch.search.aggregations.bucket.range.Range;</code></pre>
</div>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java">// sr is here your SearchResponse object
Range agg = sr.getAggregations().get("agg");

// For each entry
for (Range.Bucket entry : agg.getBuckets()) {
    String key = entry.getKeyAsString();             // Range as key
    Number from = (Number) entry.getFrom();          // Bucket from
    Number to = (Number) entry.getTo();              // Bucket to
    long docCount = entry.getDocCount();    // Doc count

    logger.info("key [{}], from [{}], to [{}], doc_count [{}]", key, from, to, docCount);
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>一般会返回如下结果:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-text" data-lang="text">key [*-1.0], from [-Infinity], to [1.0], doc_count [9]
key [1.0-1.5], from [1.0], to [1.5], doc_count [21]
key [1.5-*], from [1.5], to [Infinity], doc_count [20]</code></pre>
</div>
</div>
</div>
</div>
<div class="sect3">
<h4 id="java-aggs-bucket-daterange">7.3.11. Date Range Aggregation</h4>
<div class="paragraph">
<p>请查看
<a href="https://www.elastic.co/guide/en/elasticsearch/reference/6.8/search-aggregations-bucket-daterange-aggregation.html">Date Range Aggregation</a>
。</p>
</div>
<div class="sect4">
<h5 id="_prepare_aggregation_request_11">Prepare aggregation request</h5>
<div class="paragraph">
<p>这里有一个创建聚合请求的例子:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java">AggregationBuilder aggregation =
        AggregationBuilders
                .dateRange("agg")
                .field("dateOfBirth")
                .format("yyyy")
                .addUnboundedTo("1950")    // from -infinity to 1950 (excluded)
                .addRange("1950", "1960")  // from 1950 to 1960 (excluded)
                .addUnboundedFrom("1960"); // from 1960 to +infinity</code></pre>
</div>
</div>
</div>
<div class="sect4">
<h5 id="_use_aggregation_response_11">Use aggregation response</h5>
<div class="paragraph">
<p>导入聚合定义类:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java">import org.elasticsearch.search.aggregations.bucket.range.Range;</code></pre>
</div>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java">// sr is here your SearchResponse object
Range agg = sr.getAggregations().get("agg");

// For each entry
for (Range.Bucket entry : agg.getBuckets()) {
    String key = entry.getKeyAsString();                // Date range as key
    DateTime fromAsDate = (DateTime) entry.getFrom();   // Date bucket from as a Date
    DateTime toAsDate = (DateTime) entry.getTo();       // Date bucket to as a Date
    long docCount = entry.getDocCount();                // Doc count

    logger.info("key [{}], from [{}], to [{}], doc_count [{}]", key, fromAsDate, toAsDate, docCount);
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>一般会返回如下结果:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-text" data-lang="text">key [*-1950], from [null], to [1950-01-01T00:00:00.000Z], doc_count [8]
key [1950-1960], from [1950-01-01T00:00:00.000Z], to [1960-01-01T00:00:00.000Z], doc_count [5]
key [1960-*], from [1960-01-01T00:00:00.000Z], to [null], doc_count [37]</code></pre>
</div>
</div>
</div>
</div>
<div class="sect3">
<h4 id="java-aggs-bucket-iprange">7.3.12. Ip Range Aggregation</h4>
<div class="paragraph">
<p>请查看
<a href="https://www.elastic.co/guide/en/elasticsearch/reference/6.8/search-aggregations-bucket-iprange-aggregation.html">Ip Range Aggregation</a>
。</p>
</div>
<div class="sect4">
<h5 id="_prepare_aggregation_request_12">Prepare aggregation request</h5>
<div class="paragraph">
<p>这里有一个创建聚合请求的例子:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java">AggregatorBuilder&lt;?&gt; aggregation =
        AggregationBuilders
                .ipRange("agg")
                .field("ip")
                .addUnboundedTo("192.168.1.0")             // from -infinity to 192.168.1.0 (excluded)
                .addRange("192.168.1.0", "192.168.2.0")    // from 192.168.1.0 to 192.168.2.0 (excluded)
                .addUnboundedFrom("192.168.2.0");          // from 192.168.2.0 to +infinity</code></pre>
</div>
</div>
<div class="paragraph">
<p>注意，你也可以使用ip掩码作为范围:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java">AggregatorBuilder&lt;?&gt; aggregation =
        AggregationBuilders
                .ipRange("agg")
                .field("ip")
                .addMaskRange("192.168.0.0/32")
                .addMaskRange("192.168.0.0/24")
                .addMaskRange("192.168.0.0/16");</code></pre>
</div>
</div>
</div>
<div class="sect4">
<h5 id="_use_aggregation_response_12">Use aggregation response</h5>
<div class="paragraph">
<p>导入聚合定义类:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java">import org.elasticsearch.search.aggregations.bucket.range.Range;</code></pre>
</div>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java">// sr is here your SearchResponse object
Range agg = sr.getAggregations().get("agg");

// For each entry
for (Range.Bucket entry : agg.getBuckets()) {
    String key = entry.getKeyAsString();            // Ip range as key
    String fromAsString = entry.getFromAsString();  // Ip bucket from as a String
    String toAsString = entry.getToAsString();      // Ip bucket to as a String
    long docCount = entry.getDocCount();            // Doc count

    logger.info("key [{}], from [{}], to [{}], doc_count [{}]", key, fromAsString, toAsString, docCount);
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>第一个请求一般会返回如下结果:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-text" data-lang="text">key [*-192.168.1.0], from [null], to [192.168.1.0], doc_count [13]
key [192.168.1.0-192.168.2.0], from [192.168.1.0], to [192.168.2.0], doc_count [14]
key [192.168.2.0-*], from [192.168.2.0], to [null], doc_count [23]</code></pre>
</div>
</div>
<div class="paragraph">
<p>第二个请求（使用IP掩码）一般会返回如下结果:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-text" data-lang="text">key [192.168.0.0/32], from [192.168.0.0], to [192.168.0.1], doc_count [0]
key [192.168.0.0/24], from [192.168.0.0], to [192.168.1.0], doc_count [13]
key [192.168.0.0/16], from [192.168.0.0], to [192.169.0.0], doc_count [50]</code></pre>
</div>
</div>
</div>
</div>
<div class="sect3">
<h4 id="java-aggs-bucket-histogram">7.3.13. Histogram Aggregation</h4>
<div class="paragraph">
<p>请查看
<a href="https://www.elastic.co/guide/en/elasticsearch/reference/6.8/search-aggregations-bucket-histogram-aggregation.html">Histogram Aggregation</a>
。</p>
</div>
<div class="sect4">
<h5 id="_prepare_aggregation_request_13">Prepare aggregation request</h5>
<div class="paragraph">
<p>这里有一个创建聚合请求的例子:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java">AggregationBuilder aggregation =
        AggregationBuilders
                .histogram("agg")
                .field("height")
                .interval(1);</code></pre>
</div>
</div>
</div>
<div class="sect4">
<h5 id="_use_aggregation_response_13">Use aggregation response</h5>
<div class="paragraph">
<p>导入聚合定义类:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java">import org.elasticsearch.search.aggregations.bucket.histogram.Histogram;</code></pre>
</div>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java">// sr is here your SearchResponse object
Histogram agg = sr.getAggregations().get("agg");

// For each entry
for (Histogram.Bucket entry : agg.getBuckets()) {
    Number key = (Number) entry.getKey();   // Key
    long docCount = entry.getDocCount();    // Doc count

    logger.info("key [{}], doc_count [{}]", key, docCount);
}</code></pre>
</div>
</div>
</div>
<div class="sect4">
<h5 id="_order_2">Order</h5>
<div class="paragraph">
<p>支持与 <a href="#java-aggs-bucket-terms"><code>Terms Aggregation</code></a> 相同的排序功能。</p>
</div>
</div>
</div>
<div class="sect3">
<h4 id="java-aggs-bucket-datehistogram">7.3.14. Date Histogram Aggregation</h4>
<div class="paragraph">
<p>请查看
<a href="https://www.elastic.co/guide/en/elasticsearch/reference/6.8/search-aggregations-bucket-datehistogram-aggregation.html">Date Histogram Aggregation</a>
。</p>
</div>
<div class="sect4">
<h5 id="_prepare_aggregation_request_14">Prepare aggregation request</h5>
<div class="paragraph">
<p>这里有一个创建聚合请求的例子:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java">AggregationBuilder aggregation =
        AggregationBuilders
                .dateHistogram("agg")
                .field("dateOfBirth")
                .dateHistogramInterval(DateHistogramInterval.YEAR);</code></pre>
</div>
</div>
<div class="paragraph">
<p>如果你想设置10天间隔:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java">AggregationBuilder aggregation =
        AggregationBuilders
                .dateHistogram("agg")
                .field("dateOfBirth")
                .dateHistogramInterval(DateHistogramInterval.days(10));</code></pre>
</div>
</div>
</div>
<div class="sect4">
<h5 id="_use_aggregation_response_14">Use aggregation response</h5>
<div class="paragraph">
<p>导入聚合定义类:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java">import org.elasticsearch.search.aggregations.bucket.histogram.Histogram;</code></pre>
</div>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java">// sr is here your SearchResponse object
Histogram agg = sr.getAggregations().get("agg");

// For each entry
for (Histogram.Bucket entry : agg.getBuckets()) {
    DateTime key = (DateTime) entry.getKey();    // Key
    String keyAsString = entry.getKeyAsString(); // Key as String
    long docCount = entry.getDocCount();         // Doc count

    logger.info("key [{}], date [{}], doc_count [{}]", keyAsString, key.getYear(), docCount);
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>一般会返回如下结果:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-text" data-lang="text">key [1942-01-01T00:00:00.000Z], date [1942], doc_count [1]
key [1945-01-01T00:00:00.000Z], date [1945], doc_count [1]
key [1946-01-01T00:00:00.000Z], date [1946], doc_count [1]
...
key [2005-01-01T00:00:00.000Z], date [2005], doc_count [1]
key [2007-01-01T00:00:00.000Z], date [2007], doc_count [2]
key [2008-01-01T00:00:00.000Z], date [2008], doc_count [3]</code></pre>
</div>
</div>
</div>
<div class="sect4">
<h5 id="_order_3">Order</h5>
<div class="paragraph">
<p>支持与 <a href="#java-aggs-bucket-terms"><code>Terms Aggregation</code></a> 相同的排序功能。</p>
</div>
</div>
</div>
<div class="sect3">
<h4 id="java-aggs-bucket-geodistance">7.3.15. Geo Distance Aggregation</h4>
<div class="paragraph">
<p>请查看
<a href="https://www.elastic.co/guide/en/elasticsearch/reference/6.8/search-aggregations-bucket-geodistance-aggregation.html">Geo Distance Aggregation</a>
。</p>
</div>
<div class="sect4">
<h5 id="_prepare_aggregation_request_15">Prepare aggregation request</h5>
<div class="paragraph">
<p>这里有一个创建聚合请求的例子:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java">AggregationBuilder aggregation =
        AggregationBuilders
                .geoDistance("agg", new GeoPoint(48.84237171118314,2.33320027692004))
                .field("address.location")
                .unit(DistanceUnit.KILOMETERS)
                .addUnboundedTo(3.0)
                .addRange(3.0, 10.0)
                .addRange(10.0, 500.0);</code></pre>
</div>
</div>
</div>
<div class="sect4">
<h5 id="_use_aggregation_response_15">Use aggregation response</h5>
<div class="paragraph">
<p>导入聚合定义类:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java">import org.elasticsearch.search.aggregations.bucket.range.Range;</code></pre>
</div>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java">// sr is here your SearchResponse object
Range agg = sr.getAggregations().get("agg");

// For each entry
for (Range.Bucket entry : agg.getBuckets()) {
    String key = entry.getKeyAsString();    // key as String
    Number from = (Number) entry.getFrom(); // bucket from value
    Number to = (Number) entry.getTo();     // bucket to value
    long docCount = entry.getDocCount();    // Doc count

    logger.info("key [{}], from [{}], to [{}], doc_count [{}]", key, from, to, docCount);
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>一般会返回如下结果:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-text" data-lang="text">key [*-3.0], from [0.0], to [3.0], doc_count [161]
key [3.0-10.0], from [3.0], to [10.0], doc_count [460]
key [10.0-500.0], from [10.0], to [500.0], doc_count [4925]</code></pre>
</div>
</div>
</div>
</div>
<div class="sect3">
<h4 id="java-aggs-bucket-geohashgrid">7.3.16. Geo Hash Grid Aggregation</h4>
<div class="paragraph">
<p>请查看
<a href="https://www.elastic.co/guide/en/elasticsearch/reference/6.8/search-aggregations-bucket-geohashgrid-aggregation.html">Geo Hash Grid Aggregation</a>
。</p>
</div>
<div class="sect4">
<h5 id="_prepare_aggregation_request_16">Prepare aggregation request</h5>
<div class="paragraph">
<p>这里有一个创建聚合请求的例子:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java">AggregationBuilder aggregation =
        AggregationBuilders
                .geohashGrid("agg")
                .field("address.location")
                .precision(4);</code></pre>
</div>
</div>
</div>
<div class="sect4">
<h5 id="_use_aggregation_response_16">Use aggregation response</h5>
<div class="paragraph">
<p>导入聚合定义类:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java">import org.elasticsearch.search.aggregations.bucket.geogrid.GeoHashGrid;</code></pre>
</div>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java">// sr is here your SearchResponse object
GeoHashGrid agg = sr.getAggregations().get("agg");

// For each entry
for (GeoHashGrid.Bucket entry : agg.getBuckets()) {
    String keyAsString = entry.getKeyAsString(); // key as String
    GeoPoint key = (GeoPoint) entry.getKey();    // key as geo point
    long docCount = entry.getDocCount();         // Doc count

    logger.info("key [{}], point {}, doc_count [{}]", keyAsString, key, docCount);
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>一般会返回如下结果:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-text" data-lang="text">key [gbqu], point [47.197265625, -1.58203125], doc_count [1282]
key [gbvn], point [50.361328125, -4.04296875], doc_count [1248]
key [u1j0], point [50.712890625, 7.20703125], doc_count [1156]
key [u0j2], point [45.087890625, 7.55859375], doc_count [1138]
...</code></pre>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="java-query-dsl">8. Query DSL</h2>
<div class="sectionbody">
<div class="paragraph">
<p>Elasticsearch以类似于 REST <a href="https://www.elastic.co/guide/en/elasticsearch/reference/6.8/query-dsl.html">Query DSL</a> 的方式提供了一套完整的java query dsl(Domain Specific Language)。
查询语句构建的factory是 <code>QueryBuilders</code> 。
查询准备就绪之后就可以使用 <a href="#java-search">Search API</a> 了。</p>
</div>
<div class="paragraph">
<p>要使用 <code>QueryBuilders</code> 只需要在类中引入它们:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java">import static org.elasticsearch.index.query.QueryBuilders.*;</code></pre>
</div>
</div>
<div class="paragraph">
<p>注意可以使用 <code>QueryBuilder</code> 类中的 <code>toString()</code> 方法方便的打印(调试时)查询语句生成的JSON。</p>
</div>
<div class="paragraph">
<p><code>QueryBuilder</code> 可以被用于接受查询语句的任何API中，例如 <code>count</code> 和 <code>search</code> 。</p>
</div>
<div class="sect2">
<h3 id="java-query-dsl-match-all-query">8.1. Match All Query</h3>
<div class="paragraph">
<p>请查看 <a href="https://www.elastic.co/guide/en/elasticsearch/reference/6.8/query-dsl-match-all-query.html">Match All Query</a> 。</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java">matchAllQuery();</code></pre>
</div>
</div>
</div>
<div class="sect2">
<h3 id="java-full-text-queries">8.2. Full text queries</h3>
<div class="paragraph">
<p>高级全文检索通常在全文本全字段这样的全文查询时使用，邮件的正文就是这样的例如。
它们了解如何分析所查询的字段，并在查询前将每个字段的 <code>analyzer</code> (或 <code>search_analyzer</code> )应用于查询字符串中。</p>
</div>
<div class="paragraph">
<p>该组中的查询语句包括:</p>
</div>
<div class="dlist">
<dl>
<dt class="hdlist1"><a href="#java-query-dsl-match-query"><code>match</code> query</a></dt>
<dd>
<p>执行全文检索的标准查询语句，包括模糊匹配、短语匹配和近似匹配。</p>
</dd>
<dt class="hdlist1"><a href="#java-query-dsl-multi-match-query"><code>multi_match</code> query</a></dt>
<dd>
<p><code>match</code> query 的多字段版本。</p>
</dd>
<dt class="hdlist1"><a href="#java-query-dsl-common-terms-query"><code>common_terms</code> query</a></dt>
<dd>
<p>一个更加特殊的查询语句，专门为不常用的词准备。</p>
</dd>
<dt class="hdlist1"><a href="#java-query-dsl-query-string-query"><code>query_string</code> query</a></dt>
<dd>
<p>支持Lucene的语法，允许在条件中使用 AND|OR|NOT 和单语多字段查询。
仅供专业用户使用。</p>
</dd>
<dt class="hdlist1"><a href="#java-query-dsl-simple-query-string-query"><code>simple_query_string</code></a></dt>
<dd>
<p>一个 <code>query_string</code> 语法的的更简单且更健壮版本，适合直接开放给用户。</p>
</dd>
</dl>
</div>
<div class="sect3">
<h4 id="java-query-dsl-match-query">8.2.1. Match Query</h4>
<div class="paragraph">
<p>查看 <a href="https://www.elastic.co/guide/en/elasticsearch/reference/6.8/query-dsl-match-query.html">Match Query</a></p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java">matchQuery(
        "name", <i class="conum" data-value="1"></i><b>(1)</b>
        "kimchy elasticsearch"); <i class="conum" data-value="2"></i><b>(2)</b></code></pre>
</div>
</div>
<div class="colist arabic">
<table>
<tr>
<td><i class="conum" data-value="1"></i><b>1</b></td>
<td>field</td>
</tr>
<tr>
<td><i class="conum" data-value="2"></i><b>2</b></td>
<td>text</td>
</tr>
</table>
</div>
</div>
<div class="sect3">
<h4 id="java-query-dsl-multi-match-query">8.2.2. Multi Match Query</h4>
<div class="paragraph">
<p>查看 <a href="https://www.elastic.co/guide/en/elasticsearch/reference/6.8/query-dsl-multi-match-query.html">Multi Match Query</a></p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java">multiMatchQuery(
        "kimchy elasticsearch", <i class="conum" data-value="1"></i><b>(1)</b>
        "user", "message"); <i class="conum" data-value="2"></i><b>(2)</b></code></pre>
</div>
</div>
<div class="colist arabic">
<table>
<tr>
<td><i class="conum" data-value="1"></i><b>1</b></td>
<td>text</td>
</tr>
<tr>
<td><i class="conum" data-value="2"></i><b>2</b></td>
<td>fields</td>
</tr>
</table>
</div>
</div>
<div class="sect3">
<h4 id="java-query-dsl-common-terms-query">8.2.3. Common Terms Query</h4>
<div class="paragraph">
<p>查看 <a href="https://www.elastic.co/guide/en/elasticsearch/reference/6.8/query-dsl-common-terms-query.html">Common Terms Query</a></p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java">commonTermsQuery("name", <i class="conum" data-value="1"></i><b>(1)</b>
                 "kimchy"); <i class="conum" data-value="2"></i><b>(2)</b></code></pre>
</div>
</div>
<div class="colist arabic">
<table>
<tr>
<td><i class="conum" data-value="1"></i><b>1</b></td>
<td>field</td>
</tr>
<tr>
<td><i class="conum" data-value="2"></i><b>2</b></td>
<td>value</td>
</tr>
</table>
</div>
</div>
<div class="sect3">
<h4 id="java-query-dsl-query-string-query">8.2.4. Query String Query</h4>
<div class="paragraph">
<p>查看 <a href="https://www.elastic.co/guide/en/elasticsearch/reference/6.8/query-dsl-query-string-query.html">Query String Query</a></p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java">queryStringQuery("+kimchy -elasticsearch");</code></pre>
</div>
</div>
</div>
<div class="sect3">
<h4 id="java-query-dsl-simple-query-string-query">8.2.5. Simple Query String Query</h4>
<div class="paragraph">
<p>查看 <a href="https://www.elastic.co/guide/en/elasticsearch/reference/6.8/query-dsl-simple-query-string-query.html">Simple Query String Query</a></p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java">simpleQueryStringQuery("+kimchy -elasticsearch");</code></pre>
</div>
</div>
</div>
</div>
<div class="sect2">
<h3 id="java-term-level-queries">8.3. Term level queries</h3>
<div class="paragraph">
<p>尽管 <a href="#java-full-text-queries">full text queries</a> 将在执行之前分析查询语句，
但 <em>term-level queries</em> 会按照存储在反向索引中的确切词进行操作。</p>
</div>
<div class="paragraph">
<p>这些查询语句通常使用在数字、日期和枚举等结构化数据，而不是全字符串字段。
当然也允许在分析过程之前使用 low-level 查询语句。</p>
</div>
<div class="paragraph">
<p>这一组中的查询有:</p>
</div>
<div class="dlist">
<dl>
<dt class="hdlist1"><a href="#java-query-dsl-term-query"><code>term</code> query</a></dt>
<dd>
<p>检索指定字段包含指定条件的文档。</p>
</dd>
<dt class="hdlist1"><a href="#java-query-dsl-terms-query"><code>terms</code> query</a></dt>
<dd>
<p>检索指定字段包含指定条件中的任意一个的文档。</p>
</dd>
<dt class="hdlist1"><a href="#java-query-dsl-range-query"><code>range</code> query</a></dt>
<dd>
<p>检索指定字段包含指定范围内的值（日期、数字或字符串）的文档。</p>
</dd>
<dt class="hdlist1"><a href="#java-query-dsl-exists-query"><code>exists</code> query</a></dt>
<dd>
<p>检索指定字段是否包含非空值的文档。</p>
</dd>
<dt class="hdlist1"><a href="#java-query-dsl-prefix-query"><code>prefix</code> query</a></dt>
<dd>
<p>查找指定字段是以指定的条件作为开头的文档。</p>
</dd>
<dt class="hdlist1"><a href="#java-query-dsl-wildcard-query"><code>wildcard</code> query</a></dt>
<dd>
<p>根据通配符匹配指定字段来检索文档，支持单字符匹配(<code>?</code>)和多字符匹配(<code>*</code>)。</p>
</dd>
<dt class="hdlist1"><a href="#java-query-dsl-regexp-query"><code>regexp</code> query</a></dt>
<dd>
<p>根据正则表达式匹配指定字段来检索文档。</p>
</dd>
<dt class="hdlist1"><a href="#java-query-dsl-fuzzy-query"><code>fuzzy</code> query</a></dt>
<dd>
<p>根据模糊相似词检索文档。
模糊度是根据
<a href="https://zh.wikipedia.org/wiki/%E8%90%8A%E6%96%87%E6%96%AF%E5%9D%A6%E8%B7%9D%E9%9B%A2">莱文斯坦距离</a>
1或2来衡量的
。</p>
</dd>
<dt class="hdlist1"><a href="#java-query-dsl-type-query"><code>type</code> query</a></dt>
<dd>
<p>根据指定类型检索文档。</p>
</dd>
<dt class="hdlist1"><a href="#java-query-dsl-ids-query"><code>ids</code> query</a></dt>
<dd>
<p>根据指定类型和id列表检索文档。</p>
</dd>
</dl>
</div>
<div class="sect3">
<h4 id="java-query-dsl-term-query">8.3.1. Term Query</h4>
<div class="paragraph">
<p>查看 <a href="https://www.elastic.co/guide/en/elasticsearch/reference/6.8/query-dsl-term-query.html">Term Query</a></p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java">termQuery(
        "name", <i class="conum" data-value="1"></i><b>(1)</b>
        "kimchy"); <i class="conum" data-value="2"></i><b>(2)</b></code></pre>
</div>
</div>
<div class="colist arabic">
<table>
<tr>
<td><i class="conum" data-value="1"></i><b>1</b></td>
<td>field</td>
</tr>
<tr>
<td><i class="conum" data-value="2"></i><b>2</b></td>
<td>text</td>
</tr>
</table>
</div>
</div>
<div class="sect3">
<h4 id="java-query-dsl-terms-query">8.3.2. Terms Query</h4>
<div class="paragraph">
<p>查看 <a href="https://www.elastic.co/guide/en/elasticsearch/reference/6.8/query-dsl-terms-query.html">Terms Query</a></p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java">termsQuery("tags", <i class="conum" data-value="1"></i><b>(1)</b>
        "blue", "pill"); <i class="conum" data-value="2"></i><b>(2)</b></code></pre>
</div>
</div>
<div class="colist arabic">
<table>
<tr>
<td><i class="conum" data-value="1"></i><b>1</b></td>
<td>field</td>
</tr>
<tr>
<td><i class="conum" data-value="2"></i><b>2</b></td>
<td>values</td>
</tr>
</table>
</div>
</div>
<div class="sect3">
<h4 id="java-query-dsl-range-query">8.3.3. Range Query</h4>
<div class="paragraph">
<p>查看 <a href="https://www.elastic.co/guide/en/elasticsearch/reference/6.8/query-dsl-range-query.html">Range Query</a></p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java">rangeQuery("price") <i class="conum" data-value="1"></i><b>(1)</b>
    .from(5) <i class="conum" data-value="2"></i><b>(2)</b>
    .to(10) <i class="conum" data-value="3"></i><b>(3)</b>
    .includeLower(true) <i class="conum" data-value="4"></i><b>(4)</b>
    .includeUpper(false);  <i class="conum" data-value="5"></i><b>(5)</b></code></pre>
</div>
</div>
<div class="colist arabic">
<table>
<tr>
<td><i class="conum" data-value="1"></i><b>1</b></td>
<td>字段</td>
</tr>
<tr>
<td><i class="conum" data-value="2"></i><b>2</b></td>
<td>开始</td>
</tr>
<tr>
<td><i class="conum" data-value="3"></i><b>3</b></td>
<td>结束</td>
</tr>
<tr>
<td><i class="conum" data-value="4"></i><b>4</b></td>
<td>是否包含最小值</td>
</tr>
<tr>
<td><i class="conum" data-value="5"></i><b>5</b></td>
<td>是否包含最大值</td>
</tr>
</table>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java">// 一种简单的写法是使用 gte(greater than or equal), gt, lt 或 lte(less than or equal)
rangeQuery("age") <i class="conum" data-value="1"></i><b>(1)</b>
    .gte("10") <i class="conum" data-value="2"></i><b>(2)</b>
    .lt("20"); <i class="conum" data-value="3"></i><b>(3)</b></code></pre>
</div>
</div>
<div class="colist arabic">
<table>
<tr>
<td><i class="conum" data-value="1"></i><b>1</b></td>
<td>field</td>
</tr>
<tr>
<td><i class="conum" data-value="2"></i><b>2</b></td>
<td>等价于 <code>from(10)</code> 和 <code>includeLower(true)</code> 两个条件</td>
</tr>
<tr>
<td><i class="conum" data-value="3"></i><b>3</b></td>
<td>等价于 <code>to(20)</code> 和 <code>includeUpper(false)</code> 两个条件</td>
</tr>
</table>
</div>
</div>
<div class="sect3">
<h4 id="java-query-dsl-exists-query">8.3.4. Exists Query</h4>
<div class="paragraph">
<p>查看 <a href="https://www.elastic.co/guide/en/elasticsearch/reference/6.8/query-dsl-exists-query.html">Exists Query</a>.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java">existsQuery("name"); <i class="conum" data-value="1"></i><b>(1)</b></code></pre>
</div>
</div>
<div class="colist arabic">
<table>
<tr>
<td><i class="conum" data-value="1"></i><b>1</b></td>
<td>field</td>
</tr>
</table>
</div>
</div>
<div class="sect3">
<h4 id="java-query-dsl-prefix-query">8.3.5. Prefix Query</h4>
<div class="paragraph">
<p>查看 <a href="https://www.elastic.co/guide/en/elasticsearch/reference/6.8/query-dsl-prefix-query.html">Prefix Query</a></p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java">prefixQuery(
        "brand", <i class="conum" data-value="1"></i><b>(1)</b>
        "heine"); <i class="conum" data-value="2"></i><b>(2)</b></code></pre>
</div>
</div>
<div class="colist arabic">
<table>
<tr>
<td><i class="conum" data-value="1"></i><b>1</b></td>
<td>field</td>
</tr>
<tr>
<td><i class="conum" data-value="2"></i><b>2</b></td>
<td>prefix</td>
</tr>
</table>
</div>
</div>
<div class="sect3">
<h4 id="java-query-dsl-wildcard-query">8.3.6. Wildcard Query</h4>
<div class="paragraph">
<p>查看 <a href="https://www.elastic.co/guide/en/elasticsearch/reference/6.8/query-dsl-wildcard-query.html">Wildcard Query</a></p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java">wildcardQuery(
        "user", <i class="conum" data-value="1"></i><b>(1)</b>
        "k?mch*"); <i class="conum" data-value="2"></i><b>(2)</b></code></pre>
</div>
</div>
<div class="colist arabic">
<table>
<tr>
<td><i class="conum" data-value="1"></i><b>1</b></td>
<td>字段</td>
</tr>
<tr>
<td><i class="conum" data-value="2"></i><b>2</b></td>
<td>通配符表达式</td>
</tr>
</table>
</div>
</div>
<div class="sect3">
<h4 id="java-query-dsl-regexp-query">8.3.7. Regexp Query</h4>
<div class="paragraph">
<p>查看 <a href="https://www.elastic.co/guide/en/elasticsearch/reference/6.8/query-dsl-regexp-query.html">Regexp Query</a></p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java">regexpQuery(
        "name.first", <i class="conum" data-value="1"></i><b>(1)</b>
        "s.*y"); <i class="conum" data-value="2"></i><b>(2)</b></code></pre>
</div>
</div>
<div class="colist arabic">
<table>
<tr>
<td><i class="conum" data-value="1"></i><b>1</b></td>
<td>field</td>
</tr>
<tr>
<td><i class="conum" data-value="2"></i><b>2</b></td>
<td>正则表达式</td>
</tr>
</table>
</div>
</div>
<div class="sect3">
<h4 id="java-query-dsl-fuzzy-query">8.3.8. Fuzzy Query</h4>
<div class="paragraph">
<p>查看 <a href="https://www.elastic.co/guide/en/elasticsearch/reference/6.8/query-dsl-fuzzy-query.html">Fuzzy Query</a></p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java">fuzzyQuery(
        "name", <i class="conum" data-value="1"></i><b>(1)</b>
        "kimchy"); <i class="conum" data-value="2"></i><b>(2)</b></code></pre>
</div>
</div>
<div class="colist arabic">
<table>
<tr>
<td><i class="conum" data-value="1"></i><b>1</b></td>
<td>field</td>
</tr>
<tr>
<td><i class="conum" data-value="2"></i><b>2</b></td>
<td>text</td>
</tr>
</table>
</div>
</div>
<div class="sect3">
<h4 id="java-query-dsl-type-query">8.3.9. Type Query</h4>
<div class="paragraph">
<p>查看 <a href="https://www.elastic.co/guide/en/elasticsearch/reference/6.8/query-dsl-type-query.html">Type Query</a></p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java">typeQuery("my_type"); <i class="conum" data-value="1"></i><b>(1)</b></code></pre>
</div>
</div>
<div class="colist arabic">
<table>
<tr>
<td><i class="conum" data-value="1"></i><b>1</b></td>
<td>type</td>
</tr>
</table>
</div>
</div>
<div class="sect3">
<h4 id="java-query-dsl-ids-query">8.3.10. Ids Query</h4>
<div class="paragraph">
<p>查看 <a href="https://www.elastic.co/guide/en/elasticsearch/reference/6.8/query-dsl-ids-query.html">Ids Query</a></p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java">idsQuery("my_type", "type2")
        .addIds("1", "4", "100");

idsQuery() <i class="conum" data-value="1"></i><b>(1)</b>
        .addIds("1", "4", "100");</code></pre>
</div>
</div>
<div class="colist arabic">
<table>
<tr>
<td><i class="conum" data-value="1"></i><b>1</b></td>
<td>type 是可选项</td>
</tr>
</table>
</div>
</div>
</div>
<div class="sect2">
<h3 id="java-compound-queries">8.4. Compound queries</h3>
<div class="paragraph">
<p>组合查询可以将其它组合查询，以及其它单独的查询语句合并到一起，并将结果和匹配分数组合起来。
它可以改变它们的行为，或是将查询转换为filter context。</p>
</div>
<div class="paragraph">
<p>这一组中的查询有：</p>
</div>
<div class="dlist">
<dl>
<dt class="hdlist1"><a href="#java-query-dsl-constant-score-query"><code>constant_score</code> query</a></dt>
<dd>
<p>包含其它查询的查询，但却以filter context的形式执行该语句。所有匹配到的文档都会分配相同的 "constant" <code>_score</code> 。</p>
</dd>
<dt class="hdlist1"><a href="#java-query-dsl-bool-query"><code>bool</code> query</a></dt>
<dd>
<p>使用 <code>must</code>, <code>should</code>, <code>must_not</code>, 或 <code>filter</code> 可以将多个分支或组合查询语句组合到一起。
其中 <code>must</code> 和 <code>should</code> 条件的得分会合并到一起，这是大多数时候使用的条件；
而更好的办法是使用 <code>must_not</code> 和 <code>filter</code> ，这样它们会在 filter context 中执行。</p>
</dd>
<dt class="hdlist1"><a href="#java-query-dsl-dis-max-query"><code>dis_max</code> query</a></dt>
<dd>
<p>一个接受多个查询语句的查询，匹配到任何查询子句的文档都会返回。
虽然 <code>bool</code> 语句已经将所有匹配结果的得分组合了起来，但 <code>dis_max</code> 的得分却是单条语句匹配的最高得分。</p>
</dd>
<dt class="hdlist1"><a href="#java-query-dsl-function-score-query"><code>function_score</code> query</a></dt>
<dd>
<p>使用函数修改主查询返回的分数，以考虑流行性、失效性、距离或使用脚本实现的自定义算法等因素。</p>
</dd>
<dt class="hdlist1"><a href="#java-query-dsl-boosting-query"><code>boosting</code> query</a></dt>
<dd>
<p>查询条件将会分为正匹配和负匹配。 <code>positive</code> （正确）匹配到的文档将会加分，<code>negative</code> （负面）匹配得到的文档将会减分。</p>
</dd>
</dl>
</div>
<div class="sect3">
<h4 id="java-query-dsl-constant-score-query">8.4.1. Constant Score Query</h4>
<div class="paragraph">
<p>查看 <a href="https://www.elastic.co/guide/en/elasticsearch/reference/6.8/query-dsl-constant-score-query.html">Constant Score Query</a></p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java">constantScoreQuery(
        termQuery("name","kimchy")) <i class="conum" data-value="1"></i><b>(1)</b>
    .boost(2.0f); <i class="conum" data-value="2"></i><b>(2)</b></code></pre>
</div>
</div>
<div class="colist arabic">
<table>
<tr>
<td><i class="conum" data-value="1"></i><b>1</b></td>
<td>your query</td>
</tr>
<tr>
<td><i class="conum" data-value="2"></i><b>2</b></td>
<td>query score</td>
</tr>
</table>
</div>
</div>
<div class="sect3">
<h4 id="java-query-dsl-bool-query">8.4.2. Bool Query</h4>
<div class="paragraph">
<p>查看 <a href="https://www.elastic.co/guide/en/elasticsearch/reference/6.8/query-dsl-bool-query.html">Bool Query</a></p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java">boolQuery()
        .must(termQuery("content", "test1")) <i class="conum" data-value="1"></i><b>(1)</b>
        .must(termQuery("content", "test4")) <i class="conum" data-value="1"></i><b>(1)</b>
        .mustNot(termQuery("content", "test2")) <i class="conum" data-value="2"></i><b>(2)</b>
        .should(termQuery("content", "test3")) <i class="conum" data-value="3"></i><b>(3)</b>
        .filter(termQuery("content", "test5"));  <i class="conum" data-value="4"></i><b>(4)</b></code></pre>
</div>
</div>
<div class="colist arabic">
<table>
<tr>
<td><i class="conum" data-value="1"></i><b>1</b></td>
<td>must query</td>
</tr>
<tr>
<td><i class="conum" data-value="2"></i><b>2</b></td>
<td>must not query</td>
</tr>
<tr>
<td><i class="conum" data-value="3"></i><b>3</b></td>
<td>should query</td>
</tr>
<tr>
<td><i class="conum" data-value="4"></i><b>4</b></td>
<td>绝对匹配，不参与评分。</td>
</tr>
</table>
</div>
</div>
<div class="sect3">
<h4 id="java-query-dsl-dis-max-query">8.4.3. Dis Max Query</h4>
<div class="paragraph">
<p>查看 <a href="https://www.elastic.co/guide/en/elasticsearch/reference/6.8/query-dsl-dis-max-query.html">Dis Max Query</a></p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java">disMaxQuery()
        .add(termQuery("name", "kimchy")) <i class="conum" data-value="1"></i><b>(1)</b>
        .add(termQuery("name", "elasticsearch")) <i class="conum" data-value="2"></i><b>(2)</b>
        .boost(1.2f) <i class="conum" data-value="3"></i><b>(3)</b>
        .tieBreaker(0.7f); <i class="conum" data-value="4"></i><b>(4)</b></code></pre>
</div>
</div>
<div class="colist arabic">
<table>
<tr>
<td><i class="conum" data-value="1"></i><b>1</b></td>
<td>add your queries</td>
</tr>
<tr>
<td><i class="conum" data-value="2"></i><b>2</b></td>
<td>add your queries</td>
</tr>
<tr>
<td><i class="conum" data-value="3"></i><b>3</b></td>
<td>boost factor</td>
</tr>
<tr>
<td><i class="conum" data-value="4"></i><b>4</b></td>
<td>tie breaker</td>
</tr>
</table>
</div>
</div>
<div class="sect3">
<h4 id="java-query-dsl-function-score-query">8.4.4. Function Score Query</h4>
<div class="paragraph">
<p>查看 <a href="https://www.elastic.co/guide/en/elasticsearch/reference/6.8/query-dsl-function-score-query.html">Function Score Query</a>.</p>
</div>
<div class="paragraph">
<p>想要使用 <code>ScoreFunctionBuilders</code> 只需要在类中引入:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java">import static org.elasticsearch.index.query.functionscore.ScoreFunctionBuilders.*;</code></pre>
</div>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java">FilterFunctionBuilder[] functions = {
        new FunctionScoreQueryBuilder.FilterFunctionBuilder(
                matchQuery("name", "kimchy"), <i class="conum" data-value="1"></i><b>(1)</b>
                randomFunction()), <i class="conum" data-value="2"></i><b>(2)</b>
        new FunctionScoreQueryBuilder.FilterFunctionBuilder(
                exponentialDecayFunction("age", 0L, 1L)) <i class="conum" data-value="3"></i><b>(3)</b>
};
functionScoreQuery(functions);</code></pre>
</div>
</div>
<div class="colist arabic">
<table>
<tr>
<td><i class="conum" data-value="1"></i><b>1</b></td>
<td>Add a first function based on a query</td>
</tr>
<tr>
<td><i class="conum" data-value="2"></i><b>2</b></td>
<td>And randomize the score based on a given seed</td>
</tr>
<tr>
<td><i class="conum" data-value="3"></i><b>3</b></td>
<td>Add another function based on the age field</td>
</tr>
</table>
</div>
</div>
<div class="sect3">
<h4 id="java-query-dsl-boosting-query">8.4.5. Boosting Query</h4>
<div class="paragraph">
<p>查看 <a href="https://www.elastic.co/guide/en/elasticsearch/reference/6.8/query-dsl-boosting-query.html">Boosting Query</a></p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java">boostingQuery(
            termQuery("name","kimchy"), <i class="conum" data-value="1"></i><b>(1)</b>
            termQuery("name","dadoonet")) <i class="conum" data-value="2"></i><b>(2)</b>
        .negativeBoost(0.2f); <i class="conum" data-value="3"></i><b>(3)</b></code></pre>
</div>
</div>
<div class="colist arabic">
<table>
<tr>
<td><i class="conum" data-value="1"></i><b>1</b></td>
<td>query that will promote documents</td>
</tr>
<tr>
<td><i class="conum" data-value="2"></i><b>2</b></td>
<td>query that will demote documents</td>
</tr>
<tr>
<td><i class="conum" data-value="3"></i><b>3</b></td>
<td>negative boost</td>
</tr>
</table>
</div>
</div>
</div>
<div class="sect2">
<h3 id="java-joining-queries">8.5. Joining queries</h3>
<div class="paragraph">
<p>在Elasticsearch这样的分布式系统中使用SQL风格的关联语句对性能的损耗是非常大的。
作为替代，Elasticsearch设计了两种支持水平拓展的关联操作。</p>
</div>
<div class="dlist">
<dl>
<dt class="hdlist1"><a href="#java-query-dsl-nested-query"><code>nested</code> query</a></dt>
<dd>
<p>文档可能包含 <code>nested</code> 类型的字段。
这些字段用于索引对象数组，其中每个对象都可以作为独立文档进行查询(使用 <code>nested</code> 查询)。</p>
</dd>
<dt class="hdlist1"><a href="#java-query-dsl-has-child-query"><code>has_child</code></a> 和 <a href="#java-query-dsl-has-parent-query"><code>has_parent</code></a> 查询</dt>
<dd>
<p>同一索引之中的文档可以存在父子关系。
<code>has_child</code> 查询会返回子文档匹配的父文档，而 <code>has_parent</code> 查询则会返回父文档匹配的子文档。</p>
</dd>
</dl>
</div>
<div class="sect3">
<h4 id="java-query-dsl-nested-query">8.5.1. Nested Query</h4>
<div class="paragraph">
<p>查看 <a href="https://www.elastic.co/guide/en/elasticsearch/reference/6.8/query-dsl-nested-query.html">Nested Query</a></p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java">nestedQuery(
        "obj1", <i class="conum" data-value="1"></i><b>(1)</b>
        boolQuery() <i class="conum" data-value="2"></i><b>(2)</b>
                .must(matchQuery("obj1.name", "blue"))
                .must(rangeQuery("obj1.count").gt(5)),
        ScoreMode.Avg); <i class="conum" data-value="3"></i><b>(3)</b></code></pre>
</div>
</div>
<div class="colist arabic">
<table>
<tr>
<td><i class="conum" data-value="1"></i><b>1</b></td>
<td>嵌套文档的路径</td>
</tr>
<tr>
<td><i class="conum" data-value="2"></i><b>2</b></td>
<td>查询中使用的所有字段都必须使用完整路径</td>
</tr>
<tr>
<td><i class="conum" data-value="3"></i><b>3</b></td>
<td>评分模式支持: <code>ScoreMode.Max</code>, <code>ScoreMode.Min</code>, <code>ScoreMode.Total</code>, <code>ScoreMode.Avg</code> 或 <code>ScoreMode.None</code></td>
</tr>
</table>
</div>
</div>
<div class="sect3">
<h4 id="java-query-dsl-has-child-query">8.5.2. Has Child Query</h4>
<div class="paragraph">
<p>查看 <a href="https://www.elastic.co/guide/en/elasticsearch/reference/6.8/query-dsl-has-child-query.html">Has Child Query</a></p>
</div>
<div class="paragraph">
<p>使用 <code>has_child</code> 查询的时候有一点很重要的就是使用 <code>PreBuiltTransportClient</code> 而不是普通的client。</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java">Settings settings = Settings.builder().put("cluster.name", "elasticsearch").build();
TransportClient client = new PreBuiltTransportClient(settings);
client.addTransportAddress(new TransportAddress(new InetSocketAddress(InetAddresses.forString("127.0.0.1"), 9300)));</code></pre>
</div>
</div>
<div class="paragraph">
<p>否则父子链接模块将不会被加载，同样的 <code>transport client</code> 中也不能使用 <code>has_child</code> 查询语句。</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java">JoinQueryBuilders.hasChildQuery(
        "blog_tag", <i class="conum" data-value="1"></i><b>(1)</b>
        termQuery("tag","something"), <i class="conum" data-value="2"></i><b>(2)</b>
        ScoreMode.None); <i class="conum" data-value="3"></i><b>(3)</b></code></pre>
</div>
</div>
<div class="colist arabic">
<table>
<tr>
<td><i class="conum" data-value="1"></i><b>1</b></td>
<td>child type to query against</td>
</tr>
<tr>
<td><i class="conum" data-value="2"></i><b>2</b></td>
<td>query</td>
</tr>
<tr>
<td><i class="conum" data-value="3"></i><b>3</b></td>
<td>评分模式支持: <code>ScoreMode.Avg</code>, <code>ScoreMode.Max</code>, <code>ScoreMode.Min</code>, <code>ScoreMode.None</code> 或 <code>ScoreMode.Total</code></td>
</tr>
</table>
</div>
</div>
<div class="sect3">
<h4 id="java-query-dsl-has-parent-query">8.5.3. Has Parent Query</h4>
<div class="paragraph">
<p>查看 <a href="https://www.elastic.co/guide/en/elasticsearch/reference/6.8/query-dsl-has-parent-query.html">Has Parent</a></p>
</div>
<div class="paragraph">
<p>使用 <code>has_parent</code> 查询的时候有一点很重要的就是使用 <code>PreBuiltTransportClient</code> 而不是普通的client:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java">Settings settings = Settings.builder().put("cluster.name", "elasticsearch").build();
TransportClient client = new PreBuiltTransportClient(settings);
client.addTransportAddress(new TransportAddress(new InetSocketAddress(InetAddresses.forString("127.0.0.1"), 9300)));</code></pre>
</div>
</div>
<div class="paragraph">
<p>否则父子链接模块将不会被加载，同样的 <code>transport client</code> 中也不能使用 <code>has_child</code> 查询语句。</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java">JoinQueryBuilders.hasParentQuery(
    "blog", <i class="conum" data-value="1"></i><b>(1)</b>
    termQuery("tag","something"), <i class="conum" data-value="2"></i><b>(2)</b>
    false); <i class="conum" data-value="3"></i><b>(3)</b></code></pre>
</div>
</div>
<div class="colist arabic">
<table>
<tr>
<td><i class="conum" data-value="1"></i><b>1</b></td>
<td>parent type to query against</td>
</tr>
<tr>
<td><i class="conum" data-value="2"></i><b>2</b></td>
<td>query</td>
</tr>
<tr>
<td><i class="conum" data-value="3"></i><b>3</b></td>
<td>是否将父文档匹配分数传递给子文档</td>
</tr>
</table>
</div>
</div>
</div>
<div class="sect2">
<h3 id="java-geo-queries">8.6. Geo queries</h3>
<div class="paragraph">
<p>Elasticsearch支持两种类型的地理位置数据：支持经纬度的 <code>geo_point</code> ，以及支持点、线、圆、多边形等的 <code>geo_shape</code> 。</p>
</div>
<div class="paragraph">
<p>该组中的查询语句包括:</p>
</div>
<div class="dlist">
<dl>
<dt class="hdlist1"><a href="#java-query-dsl-geo-shape-query"><code>geo_shape</code></a> 查询</dt>
<dd>
<p>可以匹配坐标与指定区域相交、不相交或包含的地理位置。</p>
</dd>
<dt class="hdlist1"><a href="#java-query-dsl-geo-bounding-box-query"><code>geo_bounding_box</code></a> 查询</dt>
<dd>
<p>可以匹配坐标在矩形区域的地理位置。</p>
</dd>
<dt class="hdlist1"><a href="#java-query-dsl-geo-distance-query"><code>geo_distance</code></a> 查询</dt>
<dd>
<p>可以查询指定坐标为中心点指定距离内的地理位置。</p>
</dd>
<dt class="hdlist1"><a href="#java-query-dsl-geo-polygon-query"><code>geo_polygon</code></a> 查询</dt>
<dd>
<p>可以查询坐标在多边形范围内的地理位置。</p>
</dd>
</dl>
</div>
<div class="sect3">
<h4 id="java-query-dsl-geo-shape-query">8.6.1. GeoShape Query</h4>
<div class="paragraph">
<p>查看 <a href="https://www.elastic.co/guide/en/elasticsearch/reference/6.8/query-dsl-geo-shape-query.html">Geo Shape Query</a></p>
</div>
<div class="paragraph">
<p>Note: <code>geo_shape</code> 类型使用 <code>Spatial4J</code> 和 <code>JTS</code> 两种依赖。
因此，必须将 <code>Spatial4J</code> 和 <code>JTS</code> 添加到 classpath中才能使用这种类型:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-xml" data-lang="xml">&lt;dependency&gt;
    &lt;groupId&gt;org.locationtech.spatial4j&lt;/groupId&gt;
    &lt;artifactId&gt;spatial4j&lt;/artifactId&gt;
    &lt;version&gt;0.7&lt;/version&gt;  <i class="conum" data-value="1"></i><b>(1)</b>
&lt;/dependency&gt;

&lt;dependency&gt;
    &lt;groupId&gt;org.locationtech.jts&lt;/groupId&gt;
    &lt;artifactId&gt;jts-core&lt;/artifactId&gt;
    &lt;version&gt;1.15.0&lt;/version&gt; <i class="conum" data-value="2"></i><b>(2)</b>
    &lt;exclusions&gt;
        &lt;exclusion&gt;
            &lt;groupId&gt;xerces&lt;/groupId&gt;
            &lt;artifactId&gt;xercesImpl&lt;/artifactId&gt;
        &lt;/exclusion&gt;
    &lt;/exclusions&gt;
&lt;/dependency&gt;</code></pre>
</div>
</div>
<div class="colist arabic">
<table>
<tr>
<td><i class="conum" data-value="1"></i><b>1</b></td>
<td>在 <a href="http://search.maven.org/#search%7Cga%7C1%7Cg%3A%22org.locationtech.spatial4j%22%20AND%20a%3A%22spatial4j%22">Maven Central</a> 中查看更新</td>
</tr>
<tr>
<td><i class="conum" data-value="2"></i><b>2</b></td>
<td>在 <a href="http://search.maven.org/#search%7Cga%7C1%7Cg%3A%22org.locationtech.jts%22%20AND%20a%3A%22jts-core%22">Maven Central</a> 中查看更新</td>
</tr>
</table>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java">// Import ShapeRelation and ShapeBuilder
import org.elasticsearch.common.geo.ShapeRelation;
import org.elasticsearch.common.geo.builders.ShapeBuilder;</code></pre>
</div>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java">GeoShapeQueryBuilder qb = geoShapeQuery(
        "pin.location", <i class="conum" data-value="1"></i><b>(1)</b>
        new MultiPointBuilder( <i class="conum" data-value="2"></i><b>(2)</b>
                new CoordinatesBuilder()
            .coordinate(0, 0)
            .coordinate(0, 10)
            .coordinate(10, 10)
            .coordinate(10, 0)
            .coordinate(0, 0)
            .build()));
qb.relation(ShapeRelation.WITHIN); <i class="conum" data-value="3"></i><b>(3)</b></code></pre>
</div>
</div>
<div class="colist arabic">
<table>
<tr>
<td><i class="conum" data-value="1"></i><b>1</b></td>
<td>field</td>
</tr>
<tr>
<td><i class="conum" data-value="2"></i><b>2</b></td>
<td>shape</td>
</tr>
<tr>
<td><i class="conum" data-value="3"></i><b>3</b></td>
<td>关系可以是 <code>ShapeRelation.CONTAINS</code>, <code>ShapeRelation.WITHIN</code>, <code>ShapeRelation.INTERSECTS</code> 或 <code>ShapeRelation.DISJOINT</code></td>
</tr>
</table>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java">// Using pre-indexed shapes
GeoShapeQueryBuilder qb = geoShapeQuery(
            "pin.location", <i class="conum" data-value="1"></i><b>(1)</b>
            "DEU", <i class="conum" data-value="2"></i><b>(2)</b>
            "countries"); <i class="conum" data-value="3"></i><b>(3)</b>
qb.relation(ShapeRelation.WITHIN) <i class="conum" data-value="4"></i><b>(4)</b>
    .indexedShapeIndex("shapes") <i class="conum" data-value="5"></i><b>(5)</b>
    .indexedShapePath("location");  <i class="conum" data-value="6"></i><b>(6)</b></code></pre>
</div>
</div>
<div class="colist arabic">
<table>
<tr>
<td><i class="conum" data-value="1"></i><b>1</b></td>
<td>field</td>
</tr>
<tr>
<td><i class="conum" data-value="2"></i><b>2</b></td>
<td>包含pre-indexed形状的文档ID</td>
</tr>
<tr>
<td><i class="conum" data-value="3"></i><b>3</b></td>
<td>包含pre-indexed形状的index type</td>
</tr>
<tr>
<td><i class="conum" data-value="4"></i><b>4</b></td>
<td>relation</td>
</tr>
<tr>
<td><i class="conum" data-value="5"></i><b>5</b></td>
<td>包含pre-indexed形状的index名，默认是shapes</td>
</tr>
<tr>
<td><i class="conum" data-value="6"></i><b>6</b></td>
<td>包含pre-indexed形状的字段名，默认是&#8217;shape'</td>
</tr>
</table>
</div>
</div>
<div class="sect3">
<h4 id="java-query-dsl-geo-bounding-box-query">8.6.2. Geo Bounding Box Query</h4>
<div class="paragraph">
<p>查看 <a href="https://www.elastic.co/guide/en/elasticsearch/reference/6.8/query-dsl-geo-bounding-box-query.html">Geo Bounding Box Query</a></p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java">geoBoundingBoxQuery("pin.location") <i class="conum" data-value="1"></i><b>(1)</b>
    .setCorners(40.73, -74.1, <i class="conum" data-value="2"></i><b>(2)</b>
                40.717, -73.99); <i class="conum" data-value="3"></i><b>(3)</b></code></pre>
</div>
</div>
<div class="colist arabic">
<table>
<tr>
<td><i class="conum" data-value="1"></i><b>1</b></td>
<td>field</td>
</tr>
<tr>
<td><i class="conum" data-value="2"></i><b>2</b></td>
<td>矩形左上角的坐标点</td>
</tr>
<tr>
<td><i class="conum" data-value="3"></i><b>3</b></td>
<td>矩形右上角的坐标点</td>
</tr>
</table>
</div>
</div>
<div class="sect3">
<h4 id="java-query-dsl-geo-distance-query">8.6.3. Geo Distance Query</h4>
<div class="paragraph">
<p>查看 <a href="https://www.elastic.co/guide/en/elasticsearch/reference/6.8/query-dsl-geo-distance-query.html">Geo Distance Query</a></p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java">geoDistanceQuery("pin.location") <i class="conum" data-value="1"></i><b>(1)</b>
    .point(40, -70) <i class="conum" data-value="2"></i><b>(2)</b>
    .distance(200, DistanceUnit.KILOMETERS); <i class="conum" data-value="3"></i><b>(3)</b></code></pre>
</div>
</div>
<div class="colist arabic">
<table>
<tr>
<td><i class="conum" data-value="1"></i><b>1</b></td>
<td>field</td>
</tr>
<tr>
<td><i class="conum" data-value="2"></i><b>2</b></td>
<td>中心点坐标</td>
</tr>
<tr>
<td><i class="conum" data-value="3"></i><b>3</b></td>
<td>和中心点的距离</td>
</tr>
</table>
</div>
</div>
<div class="sect3">
<h4 id="java-query-dsl-geo-polygon-query">8.6.4. Geo Polygon Query</h4>
<div class="paragraph">
<p>查看 <a href="https://www.elastic.co/guide/en/elasticsearch/reference/6.8/query-dsl-geo-polygon-query.html">Geo Polygon Query</a></p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java">List&lt;GeoPoint&gt; points = new ArrayList&lt;GeoPoint&gt;(); <i class="conum" data-value="1"></i><b>(1)</b>
points.add(new GeoPoint(40, -70));
points.add(new GeoPoint(30, -80));
points.add(new GeoPoint(20, -90));
geoPolygonQuery("pin.location", points); <i class="conum" data-value="2"></i><b>(2)</b></code></pre>
</div>
</div>
<div class="colist arabic">
<table>
<tr>
<td><i class="conum" data-value="1"></i><b>1</b></td>
<td>添加落在多边形上的点的坐标</td>
</tr>
<tr>
<td><i class="conum" data-value="2"></i><b>2</b></td>
<td>通过字段和点初始化查询语句</td>
</tr>
</table>
</div>
</div>
</div>
<div class="sect2">
<h3 id="java-specialized-queries">8.7. Specialized queries</h3>
<div class="paragraph">
<p>该组查询中包含以下这些不适用于其它查询的语句:</p>
</div>
<div class="dlist">
<dl>
<dt class="hdlist1"><a href="#java-query-dsl-mlt-query"><code>more_like_this</code> query</a></dt>
<dd>
<p>这个查询语句可以检索出和指定的文本、文档或文档集合相似的文档。</p>
</dd>
<dt class="hdlist1"><a href="#java-query-dsl-script-query"><code>script</code> query</a></dt>
<dd>
<p>这个查询语句可以将脚本作为过滤器来适用。请查看 <a href="#java-query-dsl-function-score-query"><code>function_score</code> query</a> 。</p>
</dd>
<dt class="hdlist1"><a href="#java-query-percolate-query"><code>percolate</code> query</a></dt>
<dd>
<p>This query finds percolator queries based on documents.</p>
</dd>
<dt class="hdlist1"><a href="#java-query-dsl-wrapper-query"><code>wrapper</code> query</a></dt>
<dd>
<p>可以接受Json和Yaml类型语句的查询。</p>
</dd>
</dl>
</div>
<div class="sect3">
<h4 id="java-query-dsl-mlt-query">8.7.1. More Like This Query</h4>
<div class="paragraph">
<p>查看 <a href="https://www.elastic.co/guide/en/elasticsearch/reference/6.8/query-dsl-mlt-query.html">More Like This Query</a></p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java">String[] fields = {"name.first", "name.last"}; <i class="conum" data-value="1"></i><b>(1)</b>
String[] texts = {"text like this one"}; <i class="conum" data-value="2"></i><b>(2)</b>

moreLikeThisQuery(fields, texts, null)
    .minTermFreq(1) <i class="conum" data-value="3"></i><b>(3)</b>
    .maxQueryTerms(12); <i class="conum" data-value="4"></i><b>(4)</b></code></pre>
</div>
</div>
<div class="colist arabic">
<table>
<tr>
<td><i class="conum" data-value="1"></i><b>1</b></td>
<td>fields</td>
</tr>
<tr>
<td><i class="conum" data-value="2"></i><b>2</b></td>
<td>text</td>
</tr>
<tr>
<td><i class="conum" data-value="3"></i><b>3</b></td>
<td>忽略阈值</td>
</tr>
<tr>
<td><i class="conum" data-value="4"></i><b>4</b></td>
<td>生成语句条件的最大字数</td>
</tr>
</table>
</div>
</div>
<div class="sect3">
<h4 id="java-query-dsl-script-query">8.7.2. Script Query</h4>
<div class="paragraph">
<p>查看 <a href="https://www.elastic.co/guide/en/elasticsearch/reference/6.8/query-dsl-script-query.html">Script Query</a></p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java">scriptQuery(
        new Script("doc['num1'].value &gt; 1") <i class="conum" data-value="1"></i><b>(1)</b>
    );</code></pre>
</div>
</div>
<div class="colist arabic">
<table>
<tr>
<td><i class="conum" data-value="1"></i><b>1</b></td>
<td>定义脚本</td>
</tr>
</table>
</div>
<div class="paragraph">
<p>如果数据节点上已经存储了脚本，例如叫 <code>myscript.painless</code> :</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-painless" data-lang="painless">doc['num1'].value &gt; params.param1</code></pre>
</div>
</div>
<div class="paragraph">
<p>你就可以这样使用它:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java">Map&lt;String, Object&gt; parameters = new HashMap&lt;&gt;();
parameters.put("param1", 5);
scriptQuery(new Script(
        ScriptType.STORED, <i class="conum" data-value="1"></i><b>(1)</b>
        null, <i class="conum" data-value="2"></i><b>(2)</b>
        "myscript", <i class="conum" data-value="3"></i><b>(3)</b>
        singletonMap("param1", 5))); <i class="conum" data-value="4"></i><b>(4)</b></code></pre>
</div>
</div>
<div class="colist arabic">
<table>
<tr>
<td><i class="conum" data-value="1"></i><b>1</b></td>
<td>Script type: either <code>ScriptType.FILE</code>, <code>ScriptType.INLINE</code> or <code>ScriptType.INDEXED</code></td>
</tr>
<tr>
<td><i class="conum" data-value="2"></i><b>2</b></td>
<td>Scripting engine</td>
</tr>
<tr>
<td><i class="conum" data-value="3"></i><b>3</b></td>
<td>Script name</td>
</tr>
<tr>
<td><i class="conum" data-value="4"></i><b>4</b></td>
<td>Parameters as a <code>Map&lt;String, Object&gt;</code></td>
</tr>
</table>
</div>
</div>
<div class="sect3">
<h4 id="java-query-percolate-query">8.7.3. Percolate Query</h4>
<div class="paragraph">
<p>查看:
 * <a href="https://www.elastic.co/guide/en/elasticsearch/reference/6.8/query-dsl-percolate-query.html">Percolate Query</a></p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java">Settings settings = Settings.builder().put("cluster.name", "elasticsearch").build();
TransportClient client = new PreBuiltTransportClient(settings);
client.addTransportAddress(new TransportAddress(new InetSocketAddress(InetAddresses.forString("127.0.0.1"), 9300)));</code></pre>
</div>
</div>
<div class="paragraph">
<p>在使用 <code>percolate</code> 查询之前，应该添加 <code>percolate</code> 的映射，并且应该对包含 <code>percolate</code> 查询的文档建立索引:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java">// create an index with a percolator field with the name 'query':
client.admin().indices().prepareCreate("myIndexName")
                        .addMapping("_doc", "query", "type=percolator", "content", "type=text")
                        .get();

//This is the query we're registering in the percolator
QueryBuilder qb = termQuery("content", "amazing");

//Index the query = register it in the percolator
client.prepareIndex("myIndexName", "_doc", "myDesignatedQueryName")
    .setSource(jsonBuilder()
        .startObject()
            .field("query", qb) // Register the query
        .endObject())
    .setRefreshPolicy(RefreshPolicy.IMMEDIATE) // Needed when the query shall be available immediately
    .get();</code></pre>
</div>
</div>
<div class="paragraph">
<p>查询语句会在 <strong>myDesignatedQueryName</strong> 的下面建立索引。</p>
</div>
<div class="paragraph">
<p>为了对照已注册的查询语句检查文档，可以使用如下代码:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java">//Build a document to check against the percolator
XContentBuilder docBuilder = XContentFactory.jsonBuilder().startObject();
docBuilder.field("content", "This is amazing!");
docBuilder.endObject(); //End of the JSON root object

PercolateQueryBuilder percolateQuery = new PercolateQueryBuilder("query", "_doc", BytesReference.bytes(docBuilder));

// Percolate, by executing the percolator query in the query dsl:
SearchResponse response = client().prepareSearch("myIndexName")
        .setQuery(percolateQuery))
        .get();
//Iterate over the results
for(SearchHit hit : response.getHits()) {
    // Percolator queries as hit
}</code></pre>
</div>
</div>
</div>
<div class="sect3">
<h4 id="java-query-dsl-wrapper-query">8.7.4. Wrapper Query</h4>
<div class="paragraph">
<p>查看 <a href="https://www.elastic.co/guide/en/elasticsearch/reference/6.8/query-dsl-wrapper-query.html">Wrapper Query</a></p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java">String query = "{\"term\": {\"user\": \"kimchy\"}}"; <i class="conum" data-value="1"></i><b>(1)</b>
wrapperQuery(query);</code></pre>
</div>
</div>
<div class="colist arabic">
<table>
<tr>
<td><i class="conum" data-value="1"></i><b>1</b></td>
<td>query defined as query builder</td>
</tr>
</table>
</div>
</div>
</div>
<div class="sect2">
<h3 id="java-span-queries">8.8. Span queries</h3>
<div class="paragraph">
<p>Span queries 是一种低级别的位置查询语句，它提供对排序和相似度更专业的控制。
通常用在法律文件或专利这样非常具体的查询。</p>
</div>
<div class="paragraph">
<p>Span queries不能和non-span queries(<code>span_multi</code> query 是个例外)混合使用。</p>
</div>
<div class="paragraph">
<p>该组中包括以下查询:</p>
</div>
<div class="dlist">
<dl>
<dt class="hdlist1"><a href="#java-query-dsl-span-term-query"><code>span_term</code> query</a></dt>
<dd>
<p>等同于 <a href="#java-query-dsl-term-query"><code>term</code> query</a> ，但用于其它跨度查询。</p>
</dd>
<dt class="hdlist1"><a href="#java-query-dsl-span-multi-term-query"><code>span_multi</code> query</a></dt>
<dd>
<p>包括 <a href="#java-query-dsl-term-query"><code>term</code></a>, <a href="#java-query-dsl-range-query"><code>range</code></a>,
<a href="#java-query-dsl-prefix-query"><code>prefix</code></a>, <a href="#java-query-dsl-wildcard-query"><code>wildcard</code></a>,
<a href="#java-query-dsl-regexp-query"><code>regexp</code></a>, 或 <a href="#java-query-dsl-fuzzy-query"><code>fuzzy</code></a> 这些查询语句。</p>
</dd>
<dt class="hdlist1"><a href="#java-query-dsl-span-first-query"><code>span_first</code> query</a></dt>
<dd>
<p>接收另一个 span query，它的匹配项必须出现在该字段的前 N 个位置。</p>
</dd>
<dt class="hdlist1"><a href="#java-query-dsl-span-near-query"><code>span_near</code> query</a></dt>
<dd>
<p>接受在指定距离内其它的span queries，并且可以是以相同的顺序。</p>
</dd>
<dt class="hdlist1"><a href="#java-query-dsl-span-or-query"><code>span_or</code> query</a></dt>
<dd>
<p>将多个span queries组合起来，并返回任何匹配的文档。</p>
</dd>
<dt class="hdlist1"><a href="#java-query-dsl-span-not-query"><code>span_not</code> query</a></dt>
<dd>
<p>包含其它span query，并排除匹配的文档。</p>
</dd>
<dt class="hdlist1"><a href="#java-query-dsl-span-containing-query"><code>span_containing</code> query</a></dt>
<dd>
<p>接受一个span queries列表，但只返回两个条件都匹配的文档。</p>
</dd>
<dt class="hdlist1"><a href="#java-query-dsl-span-within-query"><code>span_within</code> query</a></dt>
<dd>
<p>只要span query落在由其它span queries中，就会返回span query的结果。</p>
</dd>
</dl>
</div>
<div class="sect3">
<h4 id="java-query-dsl-span-term-query">8.8.1. Span Term Query</h4>
<div class="paragraph">
<p>查看 <a href="https://www.elastic.co/guide/en/elasticsearch/reference/6.8/query-dsl-span-term-query.html">Span Term Query</a></p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java">spanTermQuery(
        "user",  <i class="conum" data-value="1"></i><b>(1)</b>
        "kimchy");  <i class="conum" data-value="2"></i><b>(2)</b></code></pre>
</div>
</div>
<div class="colist arabic">
<table>
<tr>
<td><i class="conum" data-value="1"></i><b>1</b></td>
<td>field</td>
</tr>
<tr>
<td><i class="conum" data-value="2"></i><b>2</b></td>
<td>value</td>
</tr>
</table>
</div>
</div>
<div class="sect3">
<h4 id="java-query-dsl-span-multi-term-query">8.8.2. Span Multi Term Query</h4>
<div class="paragraph">
<p>查看 <a href="https://www.elastic.co/guide/en/elasticsearch/reference/6.8/query-dsl-span-multi-term-query.html">Span Multi Term Query</a></p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java">spanMultiTermQueryBuilder(
        prefixQuery("user", "ki")); <i class="conum" data-value="1"></i><b>(1)</b></code></pre>
</div>
</div>
<div class="colist arabic">
<table>
<tr>
<td><i class="conum" data-value="1"></i><b>1</b></td>
<td>支持任何继承 <code>MultiTermQueryBuilder</code> 的类，比如 <code>FuzzyQueryBuilder</code> ,
<code>PrefixQueryBuilder</code>, <code>RangeQueryBuilder</code>, <code>RegexpQueryBuilder</code> 或 <code>WildcardQueryBuilder</code>.</td>
</tr>
</table>
</div>
</div>
<div class="sect3">
<h4 id="java-query-dsl-span-first-query">8.8.3. Span First Query</h4>
<div class="paragraph">
<p>查看 <a href="https://www.elastic.co/guide/en/elasticsearch/reference/6.8/query-dsl-span-first-query.html">Span First Query</a></p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java">spanFirstQuery(
        spanTermQuery("user", "kimchy"), <i class="conum" data-value="1"></i><b>(1)</b>
        3 <i class="conum" data-value="2"></i><b>(2)</b>
    );</code></pre>
</div>
</div>
<div class="colist arabic">
<table>
<tr>
<td><i class="conum" data-value="1"></i><b>1</b></td>
<td>query</td>
</tr>
<tr>
<td><i class="conum" data-value="2"></i><b>2</b></td>
<td>最大结束点位置</td>
</tr>
</table>
</div>
</div>
<div class="sect3">
<h4 id="java-query-dsl-span-near-query">8.8.4. Span Near Query</h4>
<div class="paragraph">
<p>查看 <a href="https://www.elastic.co/guide/en/elasticsearch/reference/6.8/query-dsl-span-near-query.html">Span Near Query</a></p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java">spanNearQuery(
        spanTermQuery("field","value1"), <i class="conum" data-value="1"></i><b>(1)</b>
        12) <i class="conum" data-value="2"></i><b>(2)</b>
            .addClause(spanTermQuery("field","value2")) <i class="conum" data-value="3"></i><b>(3)</b>
            .addClause(spanTermQuery("field","value3")) <i class="conum" data-value="4"></i><b>(4)</b>
            .inOrder(false); <i class="conum" data-value="5"></i><b>(5)</b></code></pre>
</div>
</div>
<div class="colist arabic">
<table>
<tr>
<td><i class="conum" data-value="1"></i><b>1</b></td>
<td>span queries 条件</td>
</tr>
<tr>
<td><i class="conum" data-value="2"></i><b>2</b></td>
<td>不匹配的最大数量</td>
</tr>
<tr>
<td><i class="conum" data-value="3"></i><b>3</b></td>
<td>span queries 条件</td>
</tr>
<tr>
<td><i class="conum" data-value="4"></i><b>4</b></td>
<td>span queries 条件</td>
</tr>
<tr>
<td><i class="conum" data-value="5"></i><b>5</b></td>
<td>匹配之后是否需要排序</td>
</tr>
</table>
</div>
</div>
<div class="sect3">
<h4 id="java-query-dsl-span-or-query">8.8.5. Span Or Query</h4>
<div class="paragraph">
<p>查看 <a href="https://www.elastic.co/guide/en/elasticsearch/reference/6.8/query-dsl-span-or-query.html">Span Or Query</a></p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java">spanOrQuery(spanTermQuery("field","value1")) <i class="conum" data-value="1"></i><b>(1)</b>
    .addClause(spanTermQuery("field","value2")) <i class="conum" data-value="2"></i><b>(2)</b>
    .addClause(spanTermQuery("field","value3")); <i class="conum" data-value="3"></i><b>(3)</b></code></pre>
</div>
</div>
<div class="colist arabic">
<table>
<tr>
<td><i class="conum" data-value="1"></i><b>1</b></td>
<td>span queries 条件</td>
</tr>
</table>
</div>
</div>
<div class="sect3">
<h4 id="java-query-dsl-span-not-query">8.8.6. Span Not Query</h4>
<div class="paragraph">
<p>查看 <a href="https://www.elastic.co/guide/en/elasticsearch/reference/6.8/query-dsl-span-not-query.html">Span Not Query</a></p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java">spanNotQuery(
        spanTermQuery("field","value1"), <i class="conum" data-value="1"></i><b>(1)</b>
        spanTermQuery("field","value2")); <i class="conum" data-value="2"></i><b>(2)</b></code></pre>
</div>
</div>
<div class="colist arabic">
<table>
<tr>
<td><i class="conum" data-value="1"></i><b>1</b></td>
<td>需要进行过滤的 span query</td>
</tr>
<tr>
<td><i class="conum" data-value="2"></i><b>2</b></td>
<td>需要排除的 span query</td>
</tr>
</table>
</div>
</div>
<div class="sect3">
<h4 id="java-query-dsl-span-containing-query">8.8.7. Span Containing Query</h4>
<div class="paragraph">
<p>查看 <a href="https://www.elastic.co/guide/en/elasticsearch/reference/6.8/query-dsl-span-containing-query.html">Span Containing Query</a></p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java">spanContainingQuery(
        spanNearQuery(spanTermQuery("field1","bar"), 5) <i class="conum" data-value="1"></i><b>(1)</b>
            .addClause(spanTermQuery("field1","baz"))
            .inOrder(true),
        spanTermQuery("field1","foo")); <i class="conum" data-value="2"></i><b>(2)</b></code></pre>
</div>
</div>
<div class="colist arabic">
<table>
<tr>
<td><i class="conum" data-value="1"></i><b>1</b></td>
<td><code>大</code> 的部分</td>
</tr>
<tr>
<td><i class="conum" data-value="2"></i><b>2</b></td>
<td><code>小</code> 的部分</td>
</tr>
</table>
</div>
</div>
<div class="sect3">
<h4 id="java-query-dsl-span-within-query">8.8.8. Span Within Query</h4>
<div class="paragraph">
<p>See <a href="https://www.elastic.co/guide/en/elasticsearch/reference/6.8/query-dsl-span-within-query.html">Span Within Query</a></p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java">spanWithinQuery(
        spanNearQuery(spanTermQuery("field1", "bar"), 5) <i class="conum" data-value="1"></i><b>(1)</b>
            .addClause(spanTermQuery("field1", "baz"))
            .inOrder(true),
        spanTermQuery("field1", "foo")); <i class="conum" data-value="2"></i><b>(2)</b></code></pre>
</div>
</div>
<div class="colist arabic">
<table>
<tr>
<td><i class="conum" data-value="1"></i><b>1</b></td>
<td><code>大</code> 的部分</td>
</tr>
<tr>
<td><i class="conum" data-value="2"></i><b>2</b></td>
<td><code>小</code> 的部分</td>
</tr>
</table>
</div>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="java-admin">9. Java API Administration</h2>
<div class="sectionbody">
<div class="paragraph">
<p>Elasticsearch提供了一套完整的JavaAPI来处理管理员任务。</p>
</div>
<div class="paragraph">
<p>想要使用它们，你需要从 <code>client</code> 中调用 <code>admin()</code> 方法来获取 <code>AdminClient</code> :</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java">AdminClient adminClient = client.admin();</code></pre>
</div>
</div>
<div class="admonitionblock note">
<table>
<tr>
<td class="icon">
<i class="fa icon-note" title="Note"></i>
</td>
<td class="content">
在这篇文档的其余部分中，我们使用 <code>client.admin()</code> 来获取。
</td>
</tr>
</table>
</div>
<div class="sect2">
<h3 id="java-admin-indices">9.1. Indices Administration</h3>
<div class="paragraph">
<p>要想访问indices JavaAPI，你需要从 <a href="#java-admin"><code>AdminClient</code></a> 类中调用 <code>indices()</code> 方法:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java">IndicesAdminClient indicesAdminClient = client.admin().indices();</code></pre>
</div>
</div>
<div class="admonitionblock note">
<table>
<tr>
<td class="icon">
<i class="fa icon-note" title="Note"></i>
</td>
<td class="content">
在这篇文档的其余部分中，我们使用 <code>client.admin()</code> 来获取。
</td>
</tr>
</table>
</div>
<div class="sect3">
<h4 id="java-admin-indices-create-index">9.1.1. Create Index</h4>
<div class="paragraph">
<p>使用 <a href="#java-admin-indices"><code>IndicesAdminClient</code></a>,
你可以使用默认设置和空映射来创建index:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java">client.admin().indices().prepareCreate("twitter").get();</code></pre>
</div>
</div>
<h5 id="java-admin-indices-create-index-settings" class="float">Index Settings</h5>
<div class="paragraph">
<p>创建的每个index都有单独的设置。</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java">client.admin().indices().prepareCreate("twitter")
        .setSettings(Settings.builder() <i class="conum" data-value="1"></i><b>(1)</b>
                .put("index.number_of_shards", 3)
                .put("index.number_of_replicas", 2)
        )
        .get(); <i class="conum" data-value="2"></i><b>(2)</b></code></pre>
</div>
</div>
<div class="colist arabic">
<table>
<tr>
<td><i class="conum" data-value="1"></i><b>1</b></td>
<td>该index的设置</td>
</tr>
<tr>
<td><i class="conum" data-value="2"></i><b>2</b></td>
<td>执行操作并等待结果</td>
</tr>
</table>
</div>
</div>
<div class="sect3">
<h4 id="java-admin-indices-put-mapping">9.1.2. Put Mapping</h4>
<div class="paragraph">
<p>你可以在创建index的时候添加映射:</p>
</div>
<div class="paragraph">
<p>You can add mappings at index creation time:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java">client.admin().indices().prepareCreate("twitter") <i class="conum" data-value="1"></i><b>(1)</b>
        .addMapping("_doc", "message", "type=text") <i class="conum" data-value="2"></i><b>(2)</b>
        .get();</code></pre>
</div>
</div>
<div class="colist arabic">
<table>
<tr>
<td><i class="conum" data-value="1"></i><b>1</b></td>
<td><a href="#java-admin-indices-create-index">Creates an index</a> 名字是 <code>twitter</code></td>
</tr>
<tr>
<td><i class="conum" data-value="2"></i><b>2</b></td>
<td>添加名为 <code>message</code> 类型为 <code>_doc</code> 的字段，该字段的数据类型为 <code>text</code></td>
</tr>
</table>
</div>
<div class="paragraph">
<p>上面的 <code>addMapping</code> 方法有几种变体，有些采用 <code>XContentBuilder</code> 或带有映射定义的 <code>Map</code> 作为参数。
请在阅读javadocs后再选择适合你的最简单的方法。</p>
</div>
<div class="paragraph">
<p>PUT mapping API还允许在创建 index 后更新映射。
在这种情况下，您可以提供一个类似于REST API语法的String映射:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java">client.admin().indices().preparePutMapping("twitter") <i class="conum" data-value="1"></i><b>(1)</b>
.setType("_doc")
.setSource("{\n" +
        "  \"properties\": {\n" +
        "    \"name\": {\n" + <i class="conum" data-value="2"></i><b>(2)</b>
        "      \"type\": \"text\"\n" +
        "    }\n" +
        "  }\n" +
        "}", XContentType.JSON)
.get();

// You can also provide the type in the source document
client.admin().indices().preparePutMapping("twitter")
.setType("_doc")
.setSource("{\n" +
        "    \"_doc\":{\n" + <i class="conum" data-value="3"></i><b>(3)</b>
        "        \"properties\": {\n" +
        "            \"name\": {\n" +
        "                \"type\": \"text\"\n" +
        "            }\n" +
        "        }\n" +
        "    }\n" +
        "}", XContentType.JSON)
.get();</code></pre>
</div>
</div>
<div class="colist arabic">
<table>
<tr>
<td><i class="conum" data-value="1"></i><b>1</b></td>
<td>修改名为 <code>twitter</code> 的 index 的映射</td>
</tr>
<tr>
<td><i class="conum" data-value="2"></i><b>2</b></td>
<td>向映射中添加一个名为 <code>name</code> 的新字段</td>
</tr>
<tr>
<td><i class="conum" data-value="3"></i><b>3</b></td>
<td>这中方式也可以在source中提供</td>
</tr>
</table>
</div>
</div>
<div class="sect3">
<h4 id="java-admin-indices-refresh">9.1.3. Refresh</h4>
<div class="paragraph">
<p>Refresh API允许显式地刷新一个或多个index:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java">client.admin().indices().prepareRefresh().get(); <i class="conum" data-value="1"></i><b>(1)</b>
client.admin().indices()
        .prepareRefresh("twitter") <i class="conum" data-value="2"></i><b>(2)</b>
        .get();
client.admin().indices()
        .prepareRefresh("twitter", "company") <i class="conum" data-value="3"></i><b>(3)</b>
        .get();</code></pre>
</div>
</div>
<div class="colist arabic">
<table>
<tr>
<td><i class="conum" data-value="1"></i><b>1</b></td>
<td>刷新所有 indices</td>
</tr>
<tr>
<td><i class="conum" data-value="2"></i><b>2</b></td>
<td>刷新单个 index</td>
</tr>
<tr>
<td><i class="conum" data-value="3"></i><b>3</b></td>
<td>刷新多个 indices</td>
</tr>
</table>
</div>
</div>
<div class="sect3">
<h4 id="java-admin-indices-get-settings">9.1.4. Get Settings</h4>
<div class="paragraph">
<p>Get settings API 允许检索 index/indices 的设置:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java">GetSettingsResponse response = client.admin().indices()
        .prepareGetSettings("company", "employee").get(); <i class="conum" data-value="1"></i><b>(1)</b>
for (ObjectObjectCursor&lt;String, Settings&gt; cursor : response.getIndexToSettings()) { <i class="conum" data-value="2"></i><b>(2)</b>
    String index = cursor.key; <i class="conum" data-value="3"></i><b>(3)</b>
    Settings settings = cursor.value; <i class="conum" data-value="4"></i><b>(4)</b>
    Integer shards = settings.getAsInt("index.number_of_shards", null); <i class="conum" data-value="5"></i><b>(5)</b>
    Integer replicas = settings.getAsInt("index.number_of_replicas", null); <i class="conum" data-value="6"></i><b>(6)</b>
}</code></pre>
</div>
</div>
<div class="colist arabic">
<table>
<tr>
<td><i class="conum" data-value="1"></i><b>1</b></td>
<td>获取 <code>company</code> 和 <code>employee</code> indices 的设置</td>
</tr>
<tr>
<td><i class="conum" data-value="2"></i><b>2</b></td>
<td>遍历结果</td>
</tr>
<tr>
<td><i class="conum" data-value="3"></i><b>3</b></td>
<td>Index 名称</td>
</tr>
<tr>
<td><i class="conum" data-value="4"></i><b>4</b></td>
<td>Index 的设置</td>
</tr>
<tr>
<td><i class="conum" data-value="5"></i><b>5</b></td>
<td>Index 的 shards 数量</td>
</tr>
<tr>
<td><i class="conum" data-value="6"></i><b>6</b></td>
<td>Index 的 replicas 数量</td>
</tr>
</table>
</div>
</div>
<div class="sect3">
<h4 id="java-admin-indices-update-settings">9.1.5. Update Indices Settings</h4>
<div class="paragraph">
<p>你可以通过调用以下代码来修改 index :</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java">client.admin().indices().prepareUpdateSettings("twitter") <i class="conum" data-value="1"></i><b>(1)</b>
        .setSettings(Settings.builder() <i class="conum" data-value="2"></i><b>(2)</b>
                .put("index.number_of_replicas", 0)
        )
        .get();</code></pre>
</div>
</div>
<div class="colist arabic">
<table>
<tr>
<td><i class="conum" data-value="1"></i><b>1</b></td>
<td>要更新的 index</td>
</tr>
<tr>
<td><i class="conum" data-value="2"></i><b>2</b></td>
<td>设置</td>
</tr>
</table>
</div>
</div>
</div>
<div class="sect2">
<h3 id="java-admin-cluster">9.2. Cluster Administration</h3>
<div class="paragraph">
<p>想要访问集群 Java API ，你需要从 <a href="#java-admin"><code>AdminClient</code></a> 类中调用 <code>cluster()</code> :</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java">ClusterAdminClient clusterAdminClient = client.admin().cluster();</code></pre>
</div>
</div>
<div class="admonitionblock note">
<table>
<tr>
<td class="icon">
<i class="fa icon-note" title="Note"></i>
</td>
<td class="content">
在这篇文档的其余部分中，我们使用 <code>client.admin()</code> 来获取。
</td>
</tr>
</table>
</div>
<div class="sect3">
<h4 id="java-admin-cluster-health">9.2.1. Cluster Health</h4>
<div class="sect4">
<h5 id="java-admin-cluster-health-health">Health</h5>
<div class="paragraph">
<p>Cluster Health API 可以获取集群健康的简单状态，并且还可以为您提供每个index的集群状态技术信息:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java">ClusterHealthResponse healths = client.admin().cluster().prepareHealth().get(); <i class="conum" data-value="1"></i><b>(1)</b>
String clusterName = healths.getClusterName(); <i class="conum" data-value="2"></i><b>(2)</b>
int numberOfDataNodes = healths.getNumberOfDataNodes(); <i class="conum" data-value="3"></i><b>(3)</b>
int numberOfNodes = healths.getNumberOfNodes(); <i class="conum" data-value="4"></i><b>(4)</b>

for (ClusterIndexHealth health : healths.getIndices().values()) { <i class="conum" data-value="5"></i><b>(5)</b>
    String index = health.getIndex(); <i class="conum" data-value="6"></i><b>(6)</b>
    int numberOfShards = health.getNumberOfShards(); <i class="conum" data-value="7"></i><b>(7)</b>
    int numberOfReplicas = health.getNumberOfReplicas(); <i class="conum" data-value="8"></i><b>(8)</b>
    ClusterHealthStatus status = health.getStatus(); <i class="conum" data-value="9"></i><b>(9)</b>
}</code></pre>
</div>
</div>
<div class="colist arabic">
<table>
<tr>
<td><i class="conum" data-value="1"></i><b>1</b></td>
<td>获取所有 indices 的信息</td>
</tr>
<tr>
<td><i class="conum" data-value="2"></i><b>2</b></td>
<td>获取 cluster 名称</td>
</tr>
<tr>
<td><i class="conum" data-value="3"></i><b>3</b></td>
<td>获取数据节点的数量</td>
</tr>
<tr>
<td><i class="conum" data-value="4"></i><b>4</b></td>
<td>获取节点的数量</td>
</tr>
<tr>
<td><i class="conum" data-value="5"></i><b>5</b></td>
<td>遍历所有 indices</td>
</tr>
<tr>
<td><i class="conum" data-value="6"></i><b>6</b></td>
<td>Index 名称</td>
</tr>
<tr>
<td><i class="conum" data-value="7"></i><b>7</b></td>
<td>Shards 数量</td>
</tr>
<tr>
<td><i class="conum" data-value="8"></i><b>8</b></td>
<td>Replicas 数量</td>
</tr>
<tr>
<td><i class="conum" data-value="9"></i><b>9</b></td>
<td>Index 状态</td>
</tr>
</table>
</div>
</div>
<div class="sect4">
<h5 id="java-admin-cluster-health-wait-status">Wait for status</h5>
<div class="paragraph">
<p>可以使用 cluster health API 等待整个 cluster 或给定 index 的特定状态:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java">client.admin().cluster().prepareHealth() <i class="conum" data-value="1"></i><b>(1)</b>
        .setWaitForYellowStatus() <i class="conum" data-value="2"></i><b>(2)</b>
        .get();
client.admin().cluster().prepareHealth("company") <i class="conum" data-value="3"></i><b>(3)</b>
        .setWaitForGreenStatus() <i class="conum" data-value="4"></i><b>(4)</b>
        .get();

client.admin().cluster().prepareHealth("employee") <i class="conum" data-value="5"></i><b>(5)</b>
        .setWaitForGreenStatus() <i class="conum" data-value="6"></i><b>(6)</b>
        .setTimeout(TimeValue.timeValueSeconds(2)) <i class="conum" data-value="7"></i><b>(7)</b>
        .get();</code></pre>
</div>
</div>
<div class="colist arabic">
<table>
<tr>
<td><i class="conum" data-value="1"></i><b>1</b></td>
<td>准备 health 请求</td>
</tr>
<tr>
<td><i class="conum" data-value="2"></i><b>2</b></td>
<td>等待 cluster 状态变黄</td>
</tr>
<tr>
<td><i class="conum" data-value="3"></i><b>3</b></td>
<td>为 <code>company</code> index 准备 health 请求</td>
</tr>
<tr>
<td><i class="conum" data-value="4"></i><b>4</b></td>
<td>等待 index 状态变绿</td>
</tr>
<tr>
<td><i class="conum" data-value="5"></i><b>5</b></td>
<td>为 <code>employee</code> index 准备 health 请求</td>
</tr>
<tr>
<td><i class="conum" data-value="6"></i><b>6</b></td>
<td>等待 index 状态变绿</td>
</tr>
<tr>
<td><i class="conum" data-value="7"></i><b>7</b></td>
<td>等待最多2秒</td>
</tr>
</table>
</div>
<div class="paragraph">
<p>如果 index 没有匹配预期状态，并且你希望在这种情况下返回失败，则必须明确指定:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java">ClusterHealthResponse response = client.admin().cluster().prepareHealth("company")
        .setWaitForGreenStatus() <i class="conum" data-value="1"></i><b>(1)</b>
        .get();

ClusterHealthStatus status = response.getIndices().get("company").getStatus();
if (!status.equals(ClusterHealthStatus.GREEN)) {
    throw new RuntimeException("Index is in " + status + " state"); <i class="conum" data-value="2"></i><b>(2)</b>
}</code></pre>
</div>
</div>
<div class="colist arabic">
<table>
<tr>
<td><i class="conum" data-value="1"></i><b>1</b></td>
<td>等待 index 状态变绿</td>
</tr>
<tr>
<td><i class="conum" data-value="2"></i><b>2</b></td>
<td>如果不是 <code>绿色</code> 那么就抛出一个异常</td>
</tr>
</table>
</div>
</div>
</div>
<div class="sect3">
<h4 id="stored-scripts">9.2.2. Stored Scripts API</h4>
<div class="paragraph">
<p>Stored Scripts API 允许用户与存储在 Elasticsearch 中的 scripts 和 templates 进行交互。
它可用于 create, update, get, 和 delete 存储的 scripts 和 templates。</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java">PutStoredScriptResponse response = client.admin().cluster().preparePutStoredScript()
                .setId("script1")
                .setContent(new BytesArray("{\"script\": {\"lang\": \"painless\", \"source\": \"_score * doc['my_numeric_field'].value\"} }"), XContentType.JSON)
                .get();

GetStoredScriptResponse response = client().admin().cluster().prepareGetStoredScript()
                .setId("script1")
                .get();

DeleteStoredScriptResponse response = client().admin().cluster().prepareDeleteStoredScript()
                .setId("script1")
                .get();</code></pre>
</div>
</div>
<div class="paragraph">
<p>要存储模板，只需使用 "mustache" 作为脚本语言。</p>
</div>
<div class="sect4">
<h5 id="_script_language">Script Language</h5>
<div class="paragraph">
<p>Put stored script API 允许用户设置 stored script 的语言。
如果未提供，将使用默认脚本语言。</p>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="custom-words">10. 其它</h2>
<div class="sectionbody">
<div class="paragraph">
<p>本文旨在帮助中文用户学习ElasticSearch，商业用途请提前联系作者，其余用途你随便整。</p>
</div>
<div class="admonitionblock note">
<table>
<tr>
<td class="icon">
<i class="fa icon-note" title="Note"></i>
</td>
<td class="content">
以下内容和ElasticSearch官方无关，爱看不看2333
</td>
</tr>
</table>
</div>
<div class="sect2">
<h3 id="origin-address">10.1. 原文地址</h3>
<div class="paragraph">
<p><a href="https://www.elastic.co/guide/en/elasticsearch/client/java-api/6.8/index.html">点击查看官方原文</a></p>
</div>
</div>
<div class="sect2">
<h3 id="compare-with-database">10.2. 对比关系型数据库</h3>
<div class="dlist">
<dl>
<dt class="hdlist1">名词</dt>
<dd>
<div class="ulist">
<ul>
<li>
<p>index: 索引(名词)，类似于关系型数据库(例如MySQL/SQLServer等)中的数据库(database)</p>
</li>
<li>
<p>type: 类型，类似于关系型数据库中的表格(table)</p>
</li>
<li>
<p>document: 文档，类似于关系型数据库中的一条数据</p>
</li>
<li>
<p>id: 唯一标示，类似于关系型数据库中的主键</p>
</li>
<li>
<p>bulk:批处理接口的关键字，在实际项目中你可能会经常用到它，类似于关系型数据库中的 <strong>insert into table values(x),(x),(x)</strong> 这种批处理写法。当然ES还支持批量删除和修改</p>
</li>
</ul>
</div>
</dd>
<dt class="hdlist1">动词</dt>
<dd>
<div class="ulist">
<ul>
<li>
<p>index: 索引(动词)，类似于关系型数据库中的insert</p>
</li>
<li>
<p>get: 查询，类似于关系型数据库中的select</p>
</li>
<li>
<p>delete: 删除，类似于关系型数据库中的delete</p>
</li>
<li>
<p>update: 更新，类似于关系型数据库中的update</p>
</li>
</ul>
</div>
</dd>
</dl>
</div>
<div class="admonitionblock note">
<table>
<tr>
<td class="icon">
<i class="fa icon-note" title="Note"></i>
</td>
<td class="content">
注意，名词解释只是方便理解，实现原理以及使用方法和关系型数据库有很大的区别。
</td>
</tr>
</table>
</div>
</div>
<div class="sect2">
<h3 id="translate-address">10.3. 翻译源码地址</h3>
<div class="paragraph">
<p>欢迎小伙伴贡献和指点</p>
</div>
<div class="paragraph">
<p><a href="https://gitee.com/consolelog/chinese_translation_of_elasticsearchjavaapi">码云仓库</a></p>
</div>
<div class="paragraph">
<p><a href="https://github.com/qq253498229/ElasticSearchChineseGuide">Github</a></p>
</div>
</div>
<div class="sect2">
<h3 id="update-log">10.4. 更新日志</h3>
<div class="dlist">
<dl>
<dt class="hdlist1">2019-05-28</dt>
<dd>
<p>6.8.0版本初稿完成</p>
</dd>
<dt class="hdlist1">2019-05-22</dt>
<dd>
<p>6.8.0版本正在施工, <a href="https://qq253498229.github.io/ElasticSearchChineseGuide/6.8.0/">在线地址</a>。
7.x在计划中，欢迎小伙伴们参与贡献</p>
</dd>
</dl>
</div>
</div>
</div>
</div>
</div>
</body>
</html>